Двойная точность в 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 (точного нет), но способ вывода значения скрывал эту неточность, печатая до указанного количества десятичных цифр.

Другие вопросы по тегам