美文网首页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浮点数的表示方法

相关文章

  • 浮点数陷阱

    演示代码 大家可以先猜想下结果。 结果 倒数第三行可以看到我强制退出了程序,否则会一直打印。为什么这样呢?0.1累...

  • 浮点数陷阱

    一旦我们越过了Acheron,我们就到达了第一层,这是一个善良的异教徒的家。这些人忽视浮点神,他们相信 是对的。他...

  • Java基础知识陷阱

    Java浮点数精确运算陷阱 System.out.println(2.0 - 1.1); 以上结果为0.89999...

  • 精度解决

    抓住数据的小尾巴 - JS浮点数陷阱及解法[https://zhuanlan.zhihu.com/p/30703042]

  • JavaScript之0.1+0.2=0.30000000000

    前言:在看了 JavaScript 浮点数陷阱及解法 和 探寻 JavaScript 精度问题 后,发现没有具体详...

  • java基础-浮点数陷阱

    计算机的数值采用的是二进制形式存储。根据IEEE754标准,单精度浮点数为32位: 双精度浮点数为64位: 0.9...

  • JavaScript 浮点数陷阱及解法

    数据运算类 对于运算类操作,如 +-*/,就不能使用 toPrecision 了。正确的做法是把小数转成整数后再运...

  • JavaScript 浮点数陷阱及解法

    众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇...

  • PHP浮点数精度问题

    PHP常见的浮点数“bug” 浮点数的表示形式 浮点数的表示(IEEE 754): 浮点数, 以64位的长度(双精...

  • Python 入门演示

    简单的数学运算 整数相加,得到整数: 浮点数相加,得到浮点数: 整数和浮点数相加,得到浮点数: 变量赋值 Pyth...

网友评论

    本文标题:浮点数陷阱

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