面试中,我们被问到过, 0.1 + 0.2 是否等于 0.3 这样的问题, 从而引出 javascript 中 number 运算精度问题. 因此我们来彻底 剖析下 js 中的 Number 类型
Number 资料
1. 整数
js 没有真正意义上的整数, 所有的 number 采用 IEEE 754 格式来表示, 也就是
'浮点数', 所以42.0也是整数, 他等同于'整数'42.
js 中的 '整数' 就是没有小数(小数位为 0 的除外)的十进制数
1.1 Number精度不准:
因为 js 的数字表示方式, 无论是 int ,float 他们都是 Number 类型, 然而 Number 类型是用 IEEE 754 的方案去定义的. 凡是采用这种定义的都会有 精度不准的问题
1.2 IEEE 754
由于javascript采用 IEEE754, 即 采用二进制浮点数,都并不是十分的精确 所以, 0.1 和 0.2 其实都不是十分精确的值, 所以 0.1+ 0.2 得到的不是 0.3
1.3 何为 IEEE 754 会精度不准
2. NaN
NaN不会等于自身
console.log(NaN!==NaN) // true
3. 特殊等式
Object.is() 可以用来判断两个值是否绝对相等, 是否是同一值, 但是其效率远远没有 === 高
if(!Object.is){
Object.is = function(v1, v2){
// 判断是否为 -0;
if(v1===0 && v2 ===0){
// 因为 -0 和 0 都 === 0
// 1 / -0 = -Infinity
// 1 / 0 = Infinity
return 1/v1 === 1/v2;
}
// 判断 NaN
if(v1 !== v1 ){
return v2 !== v2; // NaN !== NaN 返回 true
}
// 其他情况
return v1 ===v2;
}
}
Number 类型的相关提问:
- 如何才能让 0.1 + 0.2 === 0.3
这里我们采用一个
machine epsilon机器精度, 对于 js 来说, 应该是 2 ^ -52, 在 es6 之后为 Number.EPSILON
function numbersCloseEnough(a ,b){
return Math.abs(n1- n2)< Number.EPSILON;
}
// 如果为 true, 我们可以认为他们就是同一个值
let a = 0.1+ 0.2;
let b= 0.3;
numbersCloseEnough(a,b); // true
numbersClaseEnough(0.0000001, 0.0000002); // false
- 42.000 是不是整数
Number.isInteger(42.000) // true
在 js 中对于整数的定义不是他是否有小数点, 或者小数点之后有几位, 而是我们需要关心的是, 他除以自身得到的模是否为 0