Двойная точность в linux с помощью fpu_control.h
Я пытаюсь портировать определенный кусок кода с Solaris на Linux. В ходе этого процесса я обнаружил, что точность в linux различна, и она в расширенной точности, и нам нужно явно установить двойную точность. Для этого найдена библиотека fpu_control.h, функции FPU_GETCW и FPU_SETCW. Но даже после этого точность не устанавливается должным образом. фрагмент кода
long double power = 1.0;
#ifdef __linux
fpu_control_t mask;
_FPU_GETCW(mask);
mask &= ~(_FPU_EXTENDED & _FPU_SINGLE);
mask |= _FPU_DOUBLE;
_FPU_SETCW(mask);
power *= 0.1;
#endif
когда я печатаю power, значение равно power = 0.1000000000000000055511151231257827
Однако я ожидал, что мощность будет иметь значение 0,1. Также я использую -DDouble при компиляции. Может кто-нибудь указать мне, что происходит не так.
2 ответа
Я ожидал, что сила будет иметь значение 0,1
Как правило, невозможно оправдать ожидания ОП.
double
а также long double
не может хранить все возможные номера.double
может кодировать ровно около 264 разных чисел, так как обычно используется 64 бита.long double
может кодировать точно может быть 264, 280 или 2128 разных чисел.
С типичнымdouble
, 0.1 не может быть закодирован точно как double
, Это не одно из тех 264 точных чисел. Вместо double x = 0.1
будет инициализировать x
с ближайшей альтернативой:
Exact value 0.1000000000000000055511151231257827021181583404541015625
OP's printed value 0.1000000000000000055511151231257827
Следующая близкая альтернатива
0.09999999999999999167332731531132594682276248931884765625
Это не double
против long double
вопрос.
Вы специально запрашиваете long double
в то время как вы якобы хотите добра double
, Если ваше оборудование представляет собой процессор Intel x86/x86-64, вычисления, выполняемые через FPU, выполняются с точностью до 80 бит.
В противном случае попробуйте использовать что-то вроде флага gcc: -mfpmath=sse
, который прекратит использование FPU, и ваши операции будут выполняться с 64-битной (или двойной) точностью.
Замечания:
Вполне возможно, что даже в Solaris вы получали неточное представление о 0.1
(точного нет), но способ вывода значения скрывал эту неточность, печатая до указанного количества десятичных цифр.