JavaScript的设计缺陷?浮点运算:0.1 + 0.2 != 0.3


发布者 kris  发布时间 1416188801307
关键字 JS学习  JavaScript 
在Stackoverflow上面有这样一个提问

浮点运算的问题


在JavaScript中进行纯小数运算偶尔会得到不正确的结果:

> 0.1 + 0.2 == 0.3
false
> 0.1 + 0.2
0.30000000000000004

很多人马上就开始认为JavaScript设计的不成熟,设计上有缺陷。

实际上这并不是JavaScript仅有的问题,C/C++/Java甚至Matlab都有这个问题,参见: why 0.3-0.2-0.1 not equal to zero

 这只是JavaScript遵循IEEE 754标准所产生的必然结果。IEEE 754标准中的浮点数并不能精确地表达小数(比如说0.1),

  • 你需要足够的内存来保留5个数字
  • 你需要使用一个取值范围来确保精度。

在硬件层面,除法是转换成乖法来表示的,比如: Z = X/Y 会变成 Z = X * (1/Y);

JavaScript中的小数采用的是双精度(64位)表示的,由三部分组成: 符 + 阶码 + 尾数,在十进制中的 1/10,在十进制中可以简单写为 0.1 ,但在二进制中,他得写成:0.0001100110011001100110011001100110011001100110011001…..(后面全是 1001 循环)。因为浮点数只有52位有效数字,从第53位开始,就舍入了。这样就造成了“浮点数精度损失”问题。 (参考: 出处1出处2

所以你在处理小数运算时要非常小心。


怎么解决


就像标准中提到的,我们可以采用一个精确范围来比较是否相等

x = 0.2;
y = 0.3;
equal = (Math.abs(x - y) < 0.000001)


第二种方法是使用JavaScript内置的函数toPrecision或toFixed来保留一定的精度:

(0.1 + 0.2).toPrecision(10) == 0.3
> true
(0.1 + 0.2).toFixed(10) == 0.3
> true




回复 (18)
  • #
  • #1 夏云示 1416359592354

    醉了!

  • #2 孔四当 1416383516579

    果然等于0.30000000000000004

  • #3 bawanag 1416390416966

    这bug有点吓人啊,以后写程序小心小心

  • #4 kris 1416391787193

    @bawanag #2

    这种问题在实际中遇到的概率非常非常小,通常只要计算中有一个为含整数部的数字即可避免出现纯双精度小数的情况。

    如:

    0.1 + 0.2 + 1.0
    > 1.3
    
  • #5 龚半半 1416448931425

    public static void main(String[] args) { System.out.println(0.1+0.2); }

    0.30000000000000004

  • #6 justjavac 1416789211312
  • #7 廉迈田 1417760161411

    good

  • #8 毕出乡 1418705404645

    人收到复古风的官方个德国法国代购大股东

  • #9 TylerTemp 1418813849691

    @bawanag #2

    这不是Bug. 使用二进制必然存在的问题.

  • #10 华世丰 1439576675639

    @bawanag #2

    sb程序员才会认为这是bug.

  • #11 池片死 1466131624197

    @华世丰 #9

    别管什么原因导致的,是不是必然,计算出来的东西和预计的东西不一样就是BUG。SB才会认为错的东西是对的。

  • #12 韦虫记 1467021921221

    (0.1 + 0.2).toFixed(10) == 0.3是true 但(0.1 + 0.2).toFixed(10) === 0.3是false

  • #13 俞问州 1474363180669

    1 = 3*(1/3) = 3*0.33333333333 = 0.99999999999

  • #14 姜七世 1476264539312

    @池片死 #10

    0.1 + 0.2 結果是 0.30000000000000004 是「正確」的沒錯啊。

    JS 語言定義就是如此,當只寫 0.1 的時候 JS 預設採用 IEEE 754 來描述你的 0.1,在這個條件下 0.1 + 0.2 的結果必然就是 0.30000000000000004。

    如果你預計的答案是 0.3,那代表你用錯方法,而不是該語言的 bug。

  • #15 康汁丁 1481462193449

    ...

  • #16 没钱了 1491040931707

    有点意思

  • #17 白场以 1497173093501

    看评论原来大家读书都没认真学。。这几乎是程序入门第一课了。。。。

  • #18 傅云牛 1545205064762

    今天遇到了,感觉想不出除了控制精度以外的解决方法

微信扫码 立即评论