我现在正在开发一个程序,要求在WIN32和WIN64上获得一致的结果。我发现的一个困难是,在这些平台上对双数组值进行求和可能会导致结果不一致。以我的代码段为例:
double sum=0;
std::vector<double>::iterator itW = weighting.begin();
for(std::vector<double>::iterator it = x_array.begin(); it<x_array.end(); it++,itW++)
sum += (*it)*(*it)*(*itW);
在上述代码段中,计算了加权平方值数组的总和。
x_array
值如下所示: [size] 982 long
[capacity] 982 long
[0] 202.00000000000000 double
[1] 202.00000000000000 double
[2] 202.00000000000000 double
[3] 202.00000000000000 double
[4] 201.00000000000000 double
[5] 201.00000000000000 double
[6] 201.00000000000000 double
[7] 201.00000000000000 double
而
weighting
数组如下所示: [size] 982 long
[capacity] 982 long
[0] 3.8144169965399290e-015 double
[1] 1.0367629020002889e-014 double
[2] 2.8179334245287864e-014 double
[3] 7.6591752750373270e-014 double
[4] 2.0526158725409399e-013 double
[5] 5.5790334162148110e-013 double
[6] 1.5163876629635047e-012 double
[7] 4.1215590100336753e-012 double
我仔细检查,发现两个平台上的
x_array
和weighing
具有相同的值。但是,总和是不同的,在WIN32上,总和为575994.17931926867,而在WIN64上,总和为575994.17931926856。有什么想法为什么结果不一致?编辑:
(1)我正在使用Visual Studio 2010进行编译。
(2)/ fp分别使用精确和严格,但不会改变结果。
最佳答案
我注意到,在64位编译中,MSVC编译器更喜欢使用SSE指令,大概是通过SIMD来提高速度。在32位编译中,它使用了较早的集成x87 FPU指令。
x87浮点单元使用扩展精度80位浮点寄存器。根据您的编译器优化设置,编译器会将中间累加结果(变量和)存储在80位精度寄存器中。之所以使用额外的16位精度,是因为将两个 double 数字相乘会导致截断前产生128位精度数字。
SSE寄存器是64位IEEE double 浮点寄存器。因此,您会在第16个十进制数字中损失一点累积精度-这大约是您希望FP截断错误出现在任何双正数乘积简单总和中的位置。
有关更多详细信息,请参见"What Every Computer Scientist Should Know About Floating-Point Arithmetic" Goldberg 1991 ACM.。
关于c++ - 双数组求和结果与WIN32和WIN64上的C++不一致,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28233006/