并不是所有小数都可以用「完整」的二进制来表示的,比如十进制 0.1 在转换成二进制小数的时候,是一串无限循环的二进制数,计算机是无法表达无限循环的二进制数的,毕竟计算机的资源是有限。因此,计算机只能用「近似值」来表示该二进制,那么意味着计算机存放的小数可能不是一个真实值。
原因:在JS中采用的IEEE 754的(64位)双精度标准,计算机内部存储数据的编码的时候,0.1在计算机内部根本就不是精确的0.1,而是一个有舍入误差的0.1。当代码被编译或解释后,0.1已经被四舍五入成一个与之很接近的计算机内部数字,以至于计算还没开始,一个很小的舍入错误就已经产生了。这也就是 0.1 + 0.2 不等于0.3 的原因。
方法一:toFixed() 进行转换之后是string类型的,需要再进行强制转换
parseFloat((0.1 + 0.2).toFixed(10)) === 0.3 // true
NumberObject.toFixed(num) 方法:指定NumberObject 四舍五入为 小数位数为num 的数字。
注意:toFixed 在IE10及以上里面是正常的四舍五入;但是别的浏览器里,它不是正常的四舍五入,采用四舍六入五成双。即“4舍6入5凑偶”这里“四”是指≤4 时舍去,"六"是指≥6时进上,"五"指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:①5前为奇数,舍5入1;②5前为偶数,舍5不进。(0是偶数) 。
问题:但是在chorme(最新版),并没有完全遵守四舍六入五成双这个规则。(四舍五入有误,但不影响上述方法的结果,仍是0.3)
var a = 1.335;
console.log(a.toFixed(2))
// IE 1.34
//chorme 1.33
方法二: 可以通过引入 math.js 或者 bigNumber.js 进行解决
new BigNumber(0.2).plus(0.1).toString() // '0.3'
new BigNumber(19.9).plus(0.01).toNumber() // 19.91
方法三:分别先乘10的倍数,然后再除10
console.log(( 0.1*10 + 0.2*10 ) / 10 ) //0.3
更易懂的解释:
面试官:在JS中为什么0.2+0.1>0.3?⭐⭐⭐⭐
答:
因为在JS中,浮点数是使用64位固定长度来表示的,其中的1位表示符号位,11位用来表示指数位,剩下的52位尾数位,由于只有52位表示尾数位。
而0.1
转为二进制是一个无限循环数0.0001100110011001100......
(1100循环)
由于只能存储52位尾数位,所以会出现精度缺失,把它存到内存中再取出来转换成十进制就不是原来的0.1
了,就变成了0.100000000000000005551115123126
,而为什么02+0.1是因为
// 0.1 和 0.2 都转化成二进制后再进行运算
0.00011001100110011001100110011001100110011001100110011010 +
0.0011001100110011001100110011001100110011001100110011010 =
0.0100110011001100110011001100110011001100110011001100111
// 转成十进制正好是 0.30000000000000004
面试官:那为什么0.2+0.3=0.5呢?⭐⭐⭐⭐
// 0.2 和 0.3 都转化为二进制后再进行计算
0.001100110011001100110011001100110011001100110011001101 +
0.0100110011001100110011001100110011001100110011001101 =
0.10000000000000000000000000000000000000000000000000001 //尾数为大于52位
// 而实际取值只取52位尾数位,就变成了
0.1000000000000000000000000000000000000000000000000000 //0.5
答:0.2
和0.3
分别转换为二进制进行计算:在内存中,它们的尾数位都是等于52位的,而他们相加必定大于52位,而他们相加又恰巧前52位尾数都是0
,截取后恰好是0.1000000000000000000000000000000000000000000000000000
也就是0.5
面试官:那既然0.1不是0.1了,为什么在console.log(0.1)的时候还是0.1呢?⭐⭐⭐
答:在console.log
的时候会二进制转换为十进制,十进制再会转为字符串的形式,在转换的过程中发生了取近似值,所以打印出来的是一个近似值的字符串
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)