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