Wdrażanie podziału jednoprecyzyjnego jako mnożenie podwójnej precyzji

Pytanie

Dla kompilatora C99 implementującego dokładną arytmetykę IEEE 754, wykonaj wartościf, divisor typufloat istnieje takf / divisor != (float)(f * (1.0 / divisor))?

EDIT: Przez „implementację dokładnej arytmetyki IEEE 754” mam na myśli kompilator, który słusznie definiuje FLT_EVAL_METHOD jako 0.

Kontekst

Kompilator C, który zapewnia zgodny ze standardem IEEE 754 zmiennoprzecinkowy, może zastąpić podział jednoprecyzyjny tylko stałą przez mnożenie pojedynczej precyzji przez odwrotność, jeśli odwrotność ta jest reprezentowana dokładnie jakofloat.

W praktyce dzieje się tak tylko w przypadku dwóch mocy. Tak więc programista Alex może być tego pewienf / 2.0f zostanie skompilowany tak, jakby byłf * 0.5f, ale jeśli Alex może pomnożyć się przez0.10f zamiast dzielić przez 10, Alex powinien to wyrazić, pisząc mnożenie w programie lub używając opcji kompilatora, takiej jak GCC-ffast-math.

To pytanie dotyczy przekształcenia podziału o pojedynczej precyzji w mnożenie o podwójnej precyzji. Czy zawsze daje poprawny zaokrąglony wynik? Czy jest szansa, że ​​może być tańsza, a zatem może być optymalizacją, którą mogą wykonać kompilatory (nawet bez-ffast-math)?

Porównałam(float)(f * 0.10) if / 10.0f dla wszystkich wartości pojedynczej precyzjif między 1 a 2, bez znalezienia żadnego kontrprzykładu. Powinno to obejmować wszystkie podziały normalnefloats powoduje normalny wynik.

Następnie uogólniłem test na wszystkie dzielniki za pomocą poniższego programu:

#include <float.h>
#include <math.h>
#include <stdio.h>

int main(void){
  for (float divisor = 1.0; divisor != 2.0; divisor = nextafterf(divisor, 2.0))
    {
      double factor = 1.0 / divisor; // double-precision inverse
      for (float f = 1.0; f != 2.0; f = nextafterf(f, 2.0))
        {
          float cr = f / divisor;
          float opt = f * factor; // double-precision multiplication
          if (cr != opt)
            printf("For divisor=%a, f=%a, f/divisor=%a but (float)(f*factor)=%a\n",
                   divisor, f, cr, opt);
        }
    }
}

Przestrzeń wyszukiwania jest wystarczająco duża, aby uczynić to interesującym (246). Program jest obecnie uruchomiony. Czy ktoś może mi powiedzieć, czy coś wydrukuje, może z wyjaśnieniem, dlaczego lub dlaczego, zanim to się skończy?

questionAnswers(3)

yourAnswerToTheQuestion