使用64位或32位编译时的不同行为或sqrt

我正在使用数学库中的sqrt()函数,当我使用-m64构建64位时,我得到了正确的结果但是当我构建32位时,我的行为非常不一致.

例如在64位上

double dx = 0x1.fffffffffffffp+1023;
sqrt(dx); // => 0x1.fffffffffffffp+511
sqrt(0x1.fffffffffffffp+1023);// => 0x1.fffffffffffffp+511

(我相信这是正确的舍入结果,用mpfr验证)

但是在32位相同的输入值上,它表现不同.

double dx = 0x1.fffffffffffffp+1023;
sqrt(dx); // => 0x1.0p+512
sqrt(0x1.fffffffffffffp+1023); // => 0x1.fffffffffffffp+511

当在变量中传递相同的值时,我得到了错误的结果.
我在每次调用之前和之后检查了舍入模式,并且所有都设置为舍入到最近.
是什么原因?
我在64位机器上使用gcc 4.6,对于x86和x64两种情况,选项都是-mfpmath = sse和-march = pentium.

解决方法

您还没有说过您正在使用哪个编译器或架构,但假设g86在x86 / x86-64上,那么差异很可能是因为默认情况下gcc在32位x86上使用387个浮点指令,而它使用SSE有关x86-64的说明.

387个浮点寄存器为80位宽,而double为64位宽.这意味着使用387指令可以使中间结果具有更高的精度,这可能会在舍入后产生稍微不同的答案. (SSE2指令在打包的64位双精度数上运行).

根据您的需要,有几种方法可以改变编译器的运行方式:

>如果在x86版本中使用-ffloat-store选项,则只要将值存储在double变量中,编译器就会丢弃额外的精度.>如果在x86版本上使用-mfpmath = sse选项,并且使用-msse2或指定支持SSE2的体系结构的-march = switch,则编译器将使用SSE指令进行浮点运算,就像在x86-64上一样.但代码只能在支持SSE2的CPU上运行(Pentium-M / Pentium 4及更高版本).>如果在x86-64版本中使用-mfpmath = 387选项,编译器将使用387指令进行浮点运算,就像在x86上一样.不建议这样做 – x86-64 ABI指定在SSE寄存器中传递浮点值,因此编译器必须使用此选项在387和SSE寄存器之间进行大量的混洗.

相关文章

一.C语言中的static关键字 在C语言中,static可以用来修饰局...
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
浅谈C/C++中的指针和数组(一)指针是C/C++...
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...