IEEE 754: может ли приведение перед делением вызвать потерю точности? - PullRequest
1 голос
/ 18 июня 2019

Существуют ли два целых числа i и j, которые оба соответствуют двойному стандарту IEEE 754 (меньше DBL_MAX), но такие, что to_double(i)/to_double(j) не равен to_double(i/j), где это i/j выполняется с неограниченной точностью?

(Мы можем предположить, что to_double является округлым, даже если это имеет значение).

Мой вопрос похож на Обратимость деления IEEE 754 с плавающей запятой , но я не думаю, что это эквивалентно, или, по крайней мере, я не понимаю, как его использовать, чтобы получить пример к моему вопросу.

1 Ответ

2 голосов
/ 18 июня 2019

Да.В реализации C, где double - это базовая 64-битная двоичная с плавающей точкой IEEE-754 (с 53-битными значениями), а long double имеет 64-битные значения, выходные данные:

#include <stdio.h>

int main(void)
{
    long double x = 0x1p154L - 0x1p101L + 0x1p100L;
    long double y = 0x1p153L + 0x1p101L - 0x1p100L;
    long double z = x / y;
    double X = x;
    double Y = y;
    double Z = X/Y;
    printf("x = %La.\n", x);
    printf("y = %La.\n", y);
    printf("z = %La.\n", z);
    printf("X = %a.\n", X);
    printf("Y = %a.\n", Y);
    printf("Z = %a.\n", Z);
    printf("(double) z = %a.\n", (double) z);
}

is:

x = 0xf.ffffffffffffcp+150.
y = 0x8.0000000000004p+150.
z = 0xf.ffffffffffff4p-3.
X = 0x1p+154.
Y = 0x1p+153.
Z = 0x1p+1.
(double) z = 0x1.ffffffffffffep+0.

x / y выполняется с точностью long double, конечно, а не с бесконечной точностью, но он собирает достаточно информации, чтобы показать, что результат с бесконечной точностью будет иметь тот же конечный результат - вставка#include <math.h> и z = nexttowardl(z, INFINITY); изменяют (double) z на 0x1.fffffffffffffp+0, но это все равно не равно Z.

...