Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么相同的代码在32位和64位机器上产生不同的数值结果?_C_Floating Point - Fatal编程技术网

C 为什么相同的代码在32位和64位机器上产生不同的数值结果?

C 为什么相同的代码在32位和64位机器上产生不同的数值结果?,c,floating-point,C,Floating Point,我们正在用C编写一个数字例程库。我们还不确定是使用单精度(float)还是双精度(double),因此我们将类型SP定义为别名,直到我们决定: typedef float SP; 当我们运行单元测试时,它们都通过了我的机器(64位Ubuntu),但在我同事的机器(错误安装在64位机器上的32位Ubuntu)上失败了 使用Git的bisect命令,我们发现了在他的机器和我的机器之间产生不同结果的确切差异: -typedef double SP; +typedef float SP; 换句话说,

我们正在用C编写一个数字例程库。我们还不确定是使用单精度(
float
)还是双精度(
double
),因此我们将类型
SP
定义为别名,直到我们决定:

typedef float SP;
当我们运行单元测试时,它们都通过了我的机器(64位Ubuntu),但在我同事的机器(错误安装在64位机器上的32位Ubuntu)上失败了

使用Git的
bisect
命令,我们发现了在他的机器和我的机器之间产生不同结果的确切差异:

-typedef double SP;
+typedef float SP;
换句话说,在我们的机器上,从双精度到单精度会产生不同的数值结果(在最坏的情况下,相对差异约为1e-3)

我们非常确定,我们从不在任何地方比较无符号整数和负符号整数

为什么数字例程库在32位操作系统和64位系统上会产生不同的结果?

澄清


恐怕我还不够清楚:我们有使用双精度的Git commit
2f3f671
,并且单元测试在两台机器上都通过得一样好。然后我们有Git commit
46f2ba
,在这里我们改为单精度,这里的测试仍然在64位机器上通过,但在32位机器上没有通过。

IIRC,“double”的精度只要求=浮点的精度。因此,在一种实现中,“float”和“double”中的实际位数可能相同,而在另一种实现中则不同。这可能与平台中的32位/64位差异有关,但可能并非如此。

您遇到了通常称为“x87超精度”错误的情况

简而言之:从历史上看,x86处理器上(几乎)所有浮点计算都是使用x87指令集完成的,默认情况下,x87指令集以80位浮点类型运行,但可以通过控制寄存器中的某些位设置为以单精度或双精度(几乎)运行

如果在x87控制寄存器的精度设置为双精度或扩展精度时执行单精度操作,则结果将与在单精度中执行相同操作时产生的结果不同(除非编译器非常小心并存储每次计算的结果,然后重新加载以强制在正确的位置进行舍入。)

运行在32位上的代码使用x87单元进行浮点计算(显然控制寄存器设置为双精度),因此遇到上述问题。运行在64位上的代码使用SSE[2,3,…]浮点计算指令,它提供本机单精度和双精度运算,因此不带多余精度。这就是结果不同的原因


您可以通过告诉编译器即使在32位(
-mfpmath=SSE
和GCC)上也使用SSE进行浮点计算来解决这个问题(在一定程度上)。即使如此,位精确的结果也无法保证,因为您所链接的各种库可能使用x87,或者只是根据体系结构使用不同的算法。

您确定这是操作系统的位,而不是硬件差异吗?可能是因为:,(32位代码使用387协处理器,64位代码可能使用sse)nos是唯一正确的人。给出的答案是错误的。鉴于nos的评论,您可能应该研究优化选项对代码正确性的影响。Gcc有一些处理浮点操作行为的选项。尝试阅读生成的汇编程序,看看它们是否有显著差异在两种架构之间。下行表决是怎么回事?!我指的是浮点和双精度类型的C语言定义。这些类型不必映射到IEEE 754单精度和双精度类型。只要双精度优于或等于浮点精度,实现就符合C规范天哪,你说得对。添加
-mfpmath=sse
(但根据gcc手册,加上
-msse
)可以让它在32位机器上运行。谢谢谢谢谢谢谢谢谢谢谢谢你,你有没有关于它们为什么从FPU移动到sse的文章链接?@Skizz:没有链接,但“因为它几乎在各个方面都更好。”SSE不存在精度过高的问题,可以舍入到更小的类型而不需要存储,更好地支持处理NAN,速度更快,没有那么多隐藏的暂停,支持浮点和整数之间的转换,需要更少的内存流量。。。