dbr*_*dbr 15 c c++ floating-point precision gcc
我正在研究为什么测试用例失败
有问题的测试可以简化为执行操作(4.0/9.0) ** (1.0/2.6),将其四舍五入为6位数并检查已知值(作为字符串):
#include<stdio.h>
#include<math.h>
int main(){
printf("%.06f\n", powf(4.0/9.0, (1.0/2.6)));
}
Run Code Online (Sandbox Code Playgroud)
如果我在Linux上的gcc 4.1.2中编译并运行它,我得到:
0.732057
Run Code Online (Sandbox Code Playgroud)
Python同意,Wolfram | Alpha也是如此:
$ python2.7 -c 'print "%.06f" % (4.0/9.0)**(1/2.6)'
0.732057
Run Code Online (Sandbox Code Playgroud)
但是我在Linux上的gcc 4.4.0和OS X上的4.2.1上得到以下结果:
0.732058
Run Code Online (Sandbox Code Playgroud)
一个double行为相同(虽然我没有广泛测试此)
我不确定如何进一步缩小这个范围.这是一个gcc回归吗?舍入算法的变化?我做些傻事?
编辑:将结果打印到12位,第7位的数字是4对5,这解释了舍入差异,但不是值差:
gcc 4.1.2:
0.732057452202
Run Code Online (Sandbox Code Playgroud)
gcc 4.4.0:
0.732057511806
Run Code Online (Sandbox Code Playgroud)
以下是gcc -S两个版本的输出:https://gist.github.com/1588729
最近的gcc版本能够使用mfpr进行编译时浮点计算.我的猜测是你最近的gcc这样做并且在编译时版本中使用更高的精度.这至少是C99标准所允许的(如果它被修改,我没有查看其他标准)
C99中的6.3.1.8/2
浮动操作数的值和浮动表达式的结果可以以比该类型所需的精度和范围更高的精度和范围来表示; 因此不改变类型.
编辑:你的gcc -S结果证实了这一点.我没有检查过计算,但是旧的计算已经(在用内存替换其常量内容之后)
movss 1053092943, %xmm1
movss 1055100473, %xmm0
call powf
Run Code Online (Sandbox Code Playgroud)
用4/9.0和1/2.6的预先计算值调用powf然后将提升后的结果打印到double,而新的只打印浮动0x3f3b681f提升为double.