使用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&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...