聊聊那些年JavaScript代码中关于0.1,0.2,0.3的浮点舍入误差

首先我们看一段代码:

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

猜你喜欢

转载自blog.csdn.net/HHH_LLL/article/details/90813080