Я программирую приложение для вычисления некоторых геометрических преобразований, и пока я тестировал программу, я обнаружил нечто странное: я запустил тестирование на двух разных машинах, на рабочей станции Z400 с процессором Intel® Xeon® W3550 и Z800 с Intel Intel® Xeon® X5560, и я получил разные результаты за одну операцию:
double x = 24.169408798217777 * sin(0.59420877837561048) / sin(0.97658754841928608)
С Z400 я получил x=16.330508228047432
Пока Z800 выбрасывает это значение x=16.330508228047435
Значение отличается от последней цифры, и я делаю много вычислений с этим значением, так что это приводит к неудобствам.
Я пытался с помощью sinl
чтобы получить больше точности, но я все время получал одно и то же значение для каждой рабочей станции. Что с этим не так? Как я могу это исправить?
Результаты двух вычислений отличаются на 1 десятичную цифру, как вы заметили, и на 1 двоичную цифру, как показано ниже. Z400 ближе к правильному ответу. sin()
расчет не обязан быть точным до последнего двоичного бита, но с точностью до 1 бита. Хорошо sin()
реализация верна до последнего бита **. Ваш Z800 не так хорош.
printf("%a\n", 16.330508228047432);
printf("%a\n", 16.330508228047435);
printf("%a\n", 24.169408798217777 * sin(0.59420877837561048) / sin(0.97658754841928608)); // my PC eclipse
0x1.0549c2fee85cbp + 4
0x1.0549c2fee85ccp + 4
0x1.0549c2fee85cbp + 4
** Требования к точности — это не требование C ++, а требование IEEE с плавающей запятой. Триггерные функции с / б с точностью до 1 ульп (единица последнего места). Хорошо библиотеки trig точны в пределах 0.5 ulp (единица измерения на последнем месте) — наилучший ответ.
В качестве предположения, я собираюсь предположить, что это связано с тем, что некоторые процессоры вычисляют значения с плавающей запятой в 80-битных регистрах (вместо 64-битных) и только снижают точность настолько поздно, насколько это возможно.
В GCC вы можете отключить это (что приведет к тому, что вся ваша математика будет выполняться в 64 битах, а также, возможно, будет немного медленнее) с -ffloat-store
,
Есть несколько дополнительных предложений по этот ответ это также может помочь, если 80-битный регистр является реальной проблемой.