开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情
在 JS 中,和数字相关的类型由 Number 类型来进行表示,在这里数字可以是整数或浮点数。
那么 0.1 + 0.2 === 0.3 这个等式是否成立呢,先来运行如下代码来测试一下:
console.log(0.1 + 0.2)
console.log(0.1 + 0.2 === 0.3)
console.log(typeof (0.1 + 0.2))
console.log(typeof 0.3)
运行结果:
可以看到 0.1 + 0.2 在 JS 中的结算结果是 0.30000000000000004,其实会产生这样的结果是因为精度丢失。在两数相加时,数字会先转换成二进制,0.1 和 0.2 转换成二进制的时候尾数会无限循环,再进行对阶运算,JS 引擎对二进制进行截断后导致精度丢失。
了解这里面内在的原理,还是要从进制这里说起:
javascript 中数字类型采用的是 IEEE754 的双精度标准进行存储,可以存储的二进制精度为 64 位(小数还是整数都是 64 位),这64位包括3部分:符号位,指数位,有效位。
十进制和二进制的转换
十进制转换成二进制:
将十进制数除以 2,一直相除直到得到的商为 0,按照从低位到高位的顺序的一串由 0 和 1 组成的就是最终的二进制串。
- 0.1:0.000110011001100110011001100110011001100110011001100110011001
- 0.2:0.001100110011001100110011001100110011001100110011001100110011
二进制转换为十进制:
从二进制的低位开始,将每一位乘以2的幂数(从个位到前面的高阶位,从0开始依次累计1),小数部分与整数部分分别相加
如何使 0.1 + 0.2 == 0.3 成立?
ES6中提供了一种设置最小精度的方法 Number.EPSILON,比如:Number.EPSILON,等于 2 的-52 次方,误差如果小于这个值,就忽略不计。
function isEqual(a,b){
return Math.abs(a-b)<Number.EPSILON;
}
Number.EPSILON = Math.pow(2,-52)
console.log(isEqual(0.1 + 0.2, 0.3))
运行结果最终为 true