是否保证,无论double的初始数组的顺序如何,如果数字相同,打印出来的sum结果总是相同的?
不,FP 添加不是associative。请记住,它被称为 floating 点 - 绝对精度“浮动”大约相对于 1.0。任何给定的operation 类似添加 (+) 都受round-off error 约束。
但是,如果总和完成并且 inexact 标志是明确的,那么是的,顺序不相关。**
简单的反例。
#include <math.h>
#include <float.h>
#include <fenv.h>
#include <stdio.h>
int main(void) {
double a[3] = { DBL_MAX, -DBL_MAX, 1.0 };
fexcept_t flag;
feclearexcept(FE_ALL_EXCEPT);
printf("%e\n", (a[0] + a[1]) + a[2]);
fegetexceptflag(&flag, FE_INEXACT);
printf("Inexact %d\n", !!(flag & FE_INEXACT));
feclearexcept(FE_ALL_EXCEPT);
printf("%e\n", a[0] + (a[1] + a[2]));
fegetexceptflag(&flag, FE_INEXACT);
printf("Inexact %d\n", !!(flag & FE_INEXACT));
printf("%d\n", FLT_EVAL_METHOD);
return (EXIT_SUCCESS);
}
输出
1.000000e+00 // Sum is exact
Inexact 0
0.000000e+00 // Sum is inexact
Inexact 1
0 // evaluate all operations ... just to the range and precision of the type;
根据FLT_EVAL_METHOD,FP 数学可能会使用更宽的进动和范围,但上述极端示例的总和仍会有所不同。
** 除了可能是 0.0 与 -0.0 的结果
要了解原因,请尝试使用 4 位精度的基于 10 个文本的示例。同样的原则也适用于double,它通常具有 53 位二进制精度。
a[3] = +1.000e99, -1.000e99, 1.000
sum = a[0] + a[1] // sum now exactly 0.0
sum += a[2] // sum now exactly 1.0
// vs.
sum = a[1] + a[2] // sum now inexactly -1.000e99
sum += a[0] // sum now inexactly 0.0
Re:“打印出的总和结果将始终相同”:除非代码以足够高的精度打印 "%a" 或 "%.*e",否则打印的文本可能缺乏意义和两个不同的总和可能看起来一样。见Printf width specifier to maintain precision of floating-point value