首先我们看一段代码:
console.log(0.1+0.2); //0.30000000000000004
console.log(0.3-0.2); //0.09999999999999998
console.log(0.3-0.1); //0.19999999999999998
为什么这三个在控制台输出的值是这样的呢?
- 这个的话,我们首先从 ECMAScript(JS的三大组成部分:ES+DOM+BOM)基本数据类型中的 Number 类型说起,这种类型使用IEEE754格式来表示整数和浮点数值。
- 也正是这个IEEE754格式,所以上述JS代码在关于浮点数值的计算会产生舍入误差的问题,这是使用基于IEEE754数值的浮点计算的通病,ECMAScript并非独此一家,其他使用此格式的语言(C语言等)也存在这个问题。
- 关于IEEE二进制浮点数算术标准(IEEE754)的介绍篇幅较长,各位如果想要详细的了解这个标准的话,点击这里。
- 我们今天就说说在哪些计算情况下会发生这个舍入误差,下面分几种情况(但不止这些):
第一种,在0.3,0.2,0.1之间,哪些情况下会产生舍入误差:
console.log(0.1+0.2); //0.30000000000000004
console.log(0.3-0.2); //0.09999999999999998
console.log(0.3-0.1); //0.19999999999999998
console.log(0.1-0.3); //-0.19999999999999998
console.log(0.2-0.3); //-0.09999999999999998
但下列情况不会发生误差:
console.log(0.1-0.2); //-0.1
console.log(0.2-0.1); //0.1
第二种,通过计算得出0.3,0.2,0.1中的一个值时:
console.log(0.7-0.6); //0.09999999999999998
console.log(0.8-0.6); //0.20000000000000007
console.log(0.9-0.6); //0.30000000000000004
console.log(1.1-1); //0.10000000000000009
console.log(1.2-1); //0.19999999999999996
console.log(1.3-1); //0.30000000000000004
console.log(1.5-1.4); //0.10000000000000009
console.log(1.6-1.4); //0.20000000000000018
console.log(1.7-1.4); //0.30000000000000004
以下情况不会出现误差:
console.log(0.1-0); //0.1
console.log(0.2-0); //0.2
console.log(0.3-0); //0.3
当然,如果各位继续测试下去的话,还会有很多种其他情况,这里只是想说明一下,下次在有这种会产生舍入误差的可能时,尽量避免将其作为一个表达式与其预估结果进行比较。
if( a + b == 0.3){ //不要做这样的测试
alert("You got 0.3.")
}
2019.11.6更新:
为解决以上问题,可以用整数的乘除法来解决:
var x = 0.1
var y = 0.2
var z = (x*10 + y*10 ) / 10
if(z == 0.3){
console.log("True")
}
else{
console.log("False")
}
// 结果为True