为什么相同的代码在不同的机器上会产生两个不同的浮点结果?

4
这里是代码:

#include <iostream>
#include <math.h>

const double ln2per12 = log(2.0) / 12.0;

int main() {
    std::cout.precision(100);
    double target = 9.800000000000000710542735760100185871124267578125;
    double unnormalizatedValue = 9.79999999999063220457173883914947509765625;
    double ln2per12edValue = unnormalizatedValue * ln2per12;
    double errorLn2per12 = fabs(target - ln2per12edValue / ln2per12);
    std::cout << unnormalizatedValue << std::endl;
    std::cout << ln2per12 << std::endl;
    std::cout << errorLn2per12 << " <<<<< its different" << std::endl;
}

如果在我的机器上尝试(MSVC),或者在这里GCC):

errorLn2per12 = 9.3702823278363212011754512786865234375e-12

相反,这里GCC):

errorLn2per12 = 9.368505970996920950710773468017578125e-12

这是不同的。它是由机器epsilon引起的吗?还是编译器精度标志?或者是不同的IEEE评估?

这里漂移的原因是什么?问题似乎在于fabs()函数(因为其他值看起来都是相同的)。


2
可能是浮点数运算有问题吗?的重复问题。 - Matthieu Brucher
5
@MatthieuBrucher:请不要!这不是那个问题的重复!它是特定于平台的。请仔细阅读。 Translated: @MatthieuBrucher:请不要!这不是那个问题的重复!它是针对特定平台的。请仔细阅读。 - markzzz
3
显然不是重复的。 - YSC
4
链接可能会失效,如果这些链接包含至关重要的信息,则问题就变得毫无意义。尝试让问题自给自足。 - Some programmer dude
2
@markzzz 标志应该在问题中,而不是在外部链接后面。就我而言,如果我必须跟随一个链接,那么它并不存在于问题的一部分。 - Jesper Juhl
显示剩余9条评论
1个回答

6
即使没有使用-Ofast标志,C++标准也不要求实现在log(或sinexp等函数)方面完全准确,只需保证它们的误差在几个ulp之内(即可能存在一些二进制位上的不精确性)。这允许更快的硬件(或软件)逼近,在每个平台/编译器上可能会有所不同。
(唯一一个您始终可以在所有平台上得到完美结果的浮点数学函数是sqrt。)
更令人恼火的是,甚至在编译和运行时(例如硬件支持的逼近)之间可能会得到不同的结果。
如果您希望在所有平台和编译器上log提供完全相同的结果,则必须自己使用+-*/sqrt实现它(或找到具有此保证的库)。并且需要避免一系列陷阱。
如果您需要一般的浮点确定性,我强烈建议阅读本文以了解接下来需要解决多大的问题:https://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

还有一些不太常用的标志,可以禁止编译器在硬件自然浮点大小(通常为80位)上执行浮点运算。我曾在某处读到过相关内容。 - YSC
1
这也值得一读:计算机科学家应该了解的浮点运算知识 - Jesper Juhl
@MaxLanghof:真正的“问题”是,如果我将ln2per12作为const删除,结果仍然相同。似乎const做了一些不同的事情... http://coliru.stacked-crooked.com/a/d246fa05447efe19 - markzzz
1
@markzzz 请查看有关编译和运行时差异的段落。(还可以在“超越论”下面的链接文章中查看。)使用const,编译器可以在编译时将表达式进行常量折叠,并替换为精确值。如果没有,则必须在运行时初始化它,这可能会使用完全不同的方法来计算log - Max Langhof
删除这个问题有什么意义呢?如果你想问一个新的问题,那就直接问吧,但我不认为你会得到一个好的答案来回答“为什么gcc以不同的方式进行优化”。如果你很幸运,有人会指导你查阅优化源代码,但你能从中获得什么呢? - Max Langhof
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接