在浮点数和整数的关联加法之间加法时会发生舍入错误吗?

Could rounding error occurs in the addition between float and an associative addition of integer?

提问人:LI.LE 提问时间:1/12/2022 更新时间:1/12/2022 访问量:34

问:

(1) 我理解整数加法是关联的,例如(res1 和 res 总是产生相同的结果)

int i1, i2, i3;
int res1 = i1 + i2 + i3;
int res2 = i1 + (i2 + i3);

(2) 我也明白在以下情况下可能会出现四舍五入错误

float f = ...;
int   i1, i2, i3;
float res = f + i1 + i2 + i3 ; // rounding error may occur in `float + int`

(问题)我想知道的是,在下面的代码中,res1 和 res2 是否总是产生相同的结果(没有舍入错误)?

float f = ...;
int   i1, i2, i3;
float res1 = f + i1 + i2 + i3;
float res2 = f + (i1 + i2 + i3); // use associativity of integer addition
浮点 舍入误差 关联性

评论

0赞 Eric Postpischil 1/12/2022
i1 + i2 + i3如果出现溢出,可能会产生不同的结果。例如,可能会诱捕,而不会。i1 + (i2 + i3)INT_MAX + 1 + -1INT_MAX + (1 + -1)
0赞 LI.LE 1/12/2022
尝试过,两者都产生2147483647(INT_MAX)。
0赞 Eric Postpischil 1/12/2022
它们都是在您的 C 实现中生成的一个示例或几个示例。C 标准没有定义整数溢出的行为。在捕获溢出的 C 实现中,第一个将溢出,第二个不会。在表达式用作循环控制测试一部分的 C 实现中,优化器可能会将第一个变量视为从未发生过(创建变量从未对这些值进行过的假设,这可能会导致优化中的级联效应),而对于第二个变量则不会这样做。INT_MAX

答:

3赞 Eric Postpischil 1/12/2022 #1

此代码:

#include <stdio.h>


int main(void)
{
    float f = 0x1p25f;
    int i1 = 1, i2 = 1, i3 = 1;
    printf("%.99g\n", f + i1 + i2 + i3);
    printf("%.99g\n", f + (i1 + i2 + i3));
}

指纹:

33554432
33554436

何时使用 IEEE-754 binary32 和四舍五入到最近。float

在另一端,此代码:

#include <stdio.h>


int main(void)
{
    float f = 0x1p-24f;
    int i1 = 1, i2 = -1, i3 = 0;
    printf("%.99g\n", f + i1 + i2 + i3);
    printf("%.99g\n", f + (i1 + i2 + i3));
}

指纹:

0
5.9604644775390625e-08