如何在SUN上制作gcc以与Linux相同的方式计算浮点数

0 linux floating-point solaris

我有一个项目,我必须用双变量进行一些数学计算.问题是我在SUN Solaris 9和Linux上获得了不同的结果.有很多方法(在这里和其他论坛解释)如何使Linux作为Sun工作,但不是相反.我无法触及Linux代码,所以只有SUN才能改变.有没有办法让SUN像Linux一样行事?

我运行的代码(在两个系统上使用gcc编译):

int hash_func(char *long_id)          
{                                 
    double      product, lnum, gold;
    while (*long_id)
        lnum = lnum * 10.0 + (*long_id++ - '0');
    printf("lnum  => %20.20f\n", lnum);
    lnum = lnum * 10.0E-8;
    printf("lnum  => %20.20f\n", lnum);
    gold = 0.6125423371582974;
    product = lnum * gold;
    printf("product => %20.20f\n", product);
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果输入是339886769243483

Linux中的输出:

lnum  => 339886769243**483**.00000000000000000000

lnum  => 33988676.9243**4829473495483398**

product => 20819503.600158**59827399253845**
Run Code Online (Sandbox Code Playgroud)

在SUN上:

lnum => 339886769243483.00000000000000000000

lnum => 33988676.92434830218553543091

product = 20819503.600158**60199928283691**
Run Code Online (Sandbox Code Playgroud)

注意:结果并不总是不同,而且大多数时候它是相同的.60000中只有10个15位数字有这个问题.

请帮忙!!!

Mar*_*son 6

这里真正的答案是另一个问题:为什么你认为你需要这个?可能有更好的方法来完成您尝试做的事情,而不依赖于平台浮点的复杂细节.话说回来...

不幸的是你无法改变Linux代码,因为这里的Linux结果真的不足.SUN的结果尽可能好:它们是正确的圆形; 每次乘法都给出了与结果最接近的唯一(在这种情况下)C double.相比之下,第一个Linux乘法并没有给出正确的舍入结果.

您的Linux结果来自x86硬件上的32位系统,对吧?您显示的结果与"双舍入"现象一致并且可能由此引起:第一次乘法的结果首先舍入为64位精度(英特尔x87 FPU内部使用的精度),然后重新生成通常是双精度的53位精度.大多数时候(大约在2000年左右,大约在2000年左右)这个双轮与单轮到53位精度具有相同的效果,但偶尔会产生不同的结果,这就是你的'看到这里.

正如您所说,有一些方法可以修复Linux结果以匹配Solaris结果:其中之一是使用适当的编译器标志来强制使用SSE2指令进行浮点运算(如果可能).最近4.5版本的gcc也通过新-fexcess-precision标志修复了差异,尽管修复可能会影响不使用SSE2时的性能.

[编辑:经过几次重读gcc手册,gcc-patches邮件列表主题http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00105.html,以及相关的gcc bug报告,我还不清楚是否使用-fexcess-precision=standard确实消除了x87系统上的双舍入; 我认为答案取决于FLT_EVAL_METHOD的值.我没有32位Linux/x86机器来测试这个.]

但我不知道你是如何修复Solaris结果以匹配Linux的结果,我不确定你为什么要这样做:你会使Solaris结果不那么准确,而不是让Linux结果更多准确.

[编辑:caf在这里有一个很好的建议.在Solaris上,尝试故意使用long double作为中间结果,然后强制返回double.如果做得好,这应该重现你在Linux中看到的双舍入效果.]

请参阅David Monniaux的优秀论文验证浮点计算的缺陷,以便对双舍入进行详细解释.在早期回答中提到的Goldberg文章之后,这是必不可少的阅读.