C语言中浮点数的舍入方式 当浮点数尾数超过23位时如何对超出部分进行舍入

Nik*_*otz 3 c floating-point

在计算中

123456789 (1 110 1011 0111 1001 1010 0010 101) 
      +20 (                            10 100)
Run Code Online (Sandbox Code Playgroud)

C 中的结果是 123456816 (1 110 1011 0111 1001 1010 0110 000) 我发现它似乎被四舍五入,但在计算中

123456785 (1 110 1011 0111 1001 1010 0010 001)
      +20 (                            10 100) 
Run Code Online (Sandbox Code Playgroud)

(结果是123456800)此时看起来像是向下舍入,两者合在一起看起来像是四舍五入

123456809 (1 110 1011 0111 1001 1010 0101 001) 
Run Code Online (Sandbox Code Playgroud)

再说一遍,123456808 (1 110 1011 0111 1001 1010 0101 000)没有意义

我尝试在Google上找到答案,并总结了网友的意见,但仍然与上面的结果不符,所以我认为可能有一些细节我不知道,所以我希望你能帮助我弄清楚这个问题


添加代码来演示:

#include <stdio.h>

int main(void) {
    float x = 123456789.f;
    float y = 20.f;
    
    long m = 123456789L;
    long n = 20L;
    
    printf("As Floats, sum is: %0.1f\n", x+y);
    printf("As Longs,  sum is: %ld\n", m + n);
    
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出

As Floats, sum is: 123456816.0
As Longs,  sum is: 123456809
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 6

该代码不包含 123,456,789 和 20 的浮点加法。它包含 123,456,792 和 20 的加法。有多个步骤(以下使用floatIEEE-754 二进制 32 常用的格式,它有 24 位有效数) :

\n
    \n
  • 在 中float x = 123456789.f;,数字123456789.转换为float。转换的结果是最接近的可表示值 123,456,792,相当于 +15,432,099\xe2\x80\xa22 3。请注意,在此形式中,有效数 15,432,099 适合 24 位。(下一个较低的可表示值是 +15,432,098\xe2\x80\xa22 3 = 123,456,784,距离 123,456,789 更远。)
  • \n
  • 在 中float y = 20.f;,数字20.转换为float。转换的结果是最接近的可表示值 20。
  • \n
  • 在 中x+y,两个float值相加,因此我们将 123,456,792 和 20 相加。使用实数算术的结果将是 +15,432,099\xe2\x80\xa22 3 + 20 = +15,432,101.5\xe2\x80\xa22 3。但是,15,432,101.5 需要 25 位,因此不符合该float格式。两个最接近的可表示有效数是 15,432,101 和 15,432,102。它们同样接近,规则是使用偶数低位的数字。所以结果是 +15,432,102\xe2\x80\xa22 3 = 123,456,816。
  • \n
\n