美文网首页C语言
浮点数陷阱

浮点数陷阱

作者: 337b94dc718f | 来源:发表于2017-12-06 16:40 被阅读27次

    演示代码

        #include<stdio.h>
    
        int main () {
            double i;
            for (i = 0; i != 1; i += 0.1) {
                printf ("%lf\n", i);
            }
            return 0;
          }
    

    大家可以先猜想下结果。

    结果

    打印结果.jpg

    倒数第三行可以看到我强制退出了程序,否则会一直打印。为什么这样呢?0.1累加十次之后,不应该是1.0吗?

    原因

    1、浮点数表示方法

    根本原因是不清楚浮点数的表示方法。

    • 二进制格式

    先来说下浮点数的二进制格式,单精度浮点数采用32位bits表示,双精度浮点数采用64位bits表示。分为三部分,符号位(S)、阶码(E)和尾数(M)。

    single precision:1位符号位,8位阶码,23位尾数
    double precision:1位符号位,11位阶码,32位尾数

    符号位1表示负数,0表示正数。

    • IEEE754

    IEEE754标准中,规格化的浮点数真值表示为:
    x =(−1)s * (1.M) *2e

    其中E = [e]移码 - 1,阶码的移码即把补码标志位取反,为了能表示正负无穷大。由于尾数高位恒为1,所以只存储浮点数位M。

    • 举个栗子

    给出十进制数-4.25的机器码,使用单精度

    -4.25 = [-100.01]2,符号位为1,尾数为 1.0001,指数为2,

    所以尾数域二进制码

    M = [000 1000 0000 0000 0000 0000]2

    阶码

    E = [2]移码 - 1 = [1000 0010]2 - 1 = [1000 0001]

    得到机器码为

    -4.5 = [1100 0000 1000 1000 0000 0000 0000 0000]2

    结论

    浮点数不能精确表示某些十进制数,只能取无限近似值。将累加值换为0.5,则程序只打印两次值。

    示例代码中的0.1的累加,则是其近似值的累加,所以不会命中 1 ,程序会一直执行下去。

    参考

    IEEE754浮点数的表示方法

    相关文章

      网友评论

        本文标题:浮点数陷阱

        本文链接:https://www.haomeiwen.com/subject/sumcixtx.html