Я наблюдаю неправильное поведение округления (IMO) на некоторых платформах следующим образом:
Рассчитайте значение log(2)
в режимах округления до FE_DOWNWARD
и FE_UPWARD
(см. <fenv.h>
). Во всех случаях, которые я видел, результат округления в меньшую сторону меньше результата округления в большую сторону, чего я и ожидал (результат неточный).
Теперь, используя те же режимы округления, вызовите exp
с каждый результат. Поскольку exp
монотонно увеличивается (наклон составляет ~ 2 в интересующей области), я ожидаю, что эти результаты будут еще дальше друг от друга. Но на некоторых протестированных платформах два результата из exp
эквивалентны.
Вот простая тестовая программа:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
int main(void) {
fesetround(FE_DOWNWARD);
double xlo = log(2);
double xxlo = exp(xlo);
printf("xlo=%.16e xxlo=%.16e\n",xlo,xxlo);
fesetround(FE_UPWARD);
double xhi = log(2);
double xxhi = exp(xhi);
printf("xhi=%.16e xxhi=%.16e\n",xhi,xxhi);
printf("Delta x=%.16e\n",xhi-xlo);
if (xxlo == xxhi)
printf("FAIL\n");
else
printf("Delta xx=%.16e\n",xxhi-xxlo);
return 0;
}
Один (хороший) результат на Xeon E5520 @ 2,27 ГГц:
xlo=6.9314718055994528e-01 xxlo=1.9999999999999997e+00
xhi=6.9314718055994540e-01 xxhi=2.0000000000000005e+00
Delta x=1.1102230246251566e-16
Delta xx=6.6613381477509393e-16
Другие процессоры, прошедшие тестирование: AMD Ryzen 9 3950X, Intel i7-5557U, Intel i7-3770, Intel m7-6Y75.
Но, как сообщается, пара потерпела неудачу (xxlo == xxhi): Intel E5-2650 и AMD EPY C 7401, по совпадению оба компьютера серверного класса. У меня нет прямого доступа к ним, но запуск теста на https://repl.it/languages/c также дает сбой:
clang version 7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)
clang-7 -pthread -lm -o main main.c
./main
xlo=6.93147180559945286e-01 xxlo=2.00000000000000000e+00
xhi=6.93147180559945398e-01 xxhi=2.00000000000000000e+00
Delta x=1.11022302462515655e-16
FAIL
Меня не очень интересует фактическая точность результатов, но больше в относительных значениях. Так я что-то упустил, или это просто неправильно? И если это неправильно, это ошибка аппаратного округления или проблемы с математическими библиотеками программного обеспечения, или даже компилятор / настройки? Я также заинтересован в получении каких-либо результатов от выполнения простого теста, чтобы увидеть, можно ли сделать какие-либо дополнительные выводы из этих данных.