4

我正在编写一个计算几何变换的应用程序,在测试程序时,我发现了一些奇怪的东西:我在两台不同的机器上启动了测试,Z400 工作站配备英特尔® 至强® 处理器 W3550 和 Z800 工作站配备英特尔® Xeon® 处理器 X5560,我在一次操作中得到了不同的结果:

double x = 24.169408798217777 * sin(0.59420877837561048) / sin(0.97658754841928608)

有了 Z400,我得到了x=16.330508228047432

而 Z800 抛出这个值x=16.330508228047435

最后一位的值不同,我用那个值做了很多计算,所以很不方便。

我尝试使用sinl以获得更高的精度,但每个工作站我一直得到相同的值。它出什么问题了?我该如何解决?

4

2 回答 2

2

如您所述,2 次计算的结果相差 1 个十进制数字和 1 个二进制数字,如下所示。Z400 更接近正确答案。 sin()计算不必精确到最后一个二进制位,而是在 1 位以内。好的sin()实现对最后一点是正确的**。你的 Z800 没那么好。

printf("%a\n", 16.330508228047432);
printf("%a\n", 16.330508228047435);
printf("%a\n", 24.169408798217777 * sin(0.59420877837561048) / sin(0.97658754841928608));  // my PC eclipse

0x1.0549c2fee85cbp+4
0x1.0549c2fee85ccp+4
0x1.0549c2fee85cbp+4

** 精度要求与其说是 C++ 要求,不如说是 IEEE 浮点要求。Trig 函数 s/b 精确到 1 ulp(单位最后一个位置)。好的三角函数库在 0.5 ulp(最后一个单位)内是准确的——这是最好的答案。

于 2013-08-05T14:48:46.547 回答
1

作为猜测,我建议这与某些处理器在 80 位寄存器(而不是 64 位)中计算浮点值有关,并且尽可能晚地降低精度。

在 GCC 上,您可以使用-ffloat-store.

如果 80 位寄存器是实际问题,则有关此答案的一些其他建议也可能会有所帮助。

于 2013-08-05T14:43:23.700 回答