当前位置:嗨网首页>书籍在线阅读

06-比较数字

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

5.5 比较数字

在给数字做一致性和相等性比较的时候,需要格外小心。

首先要注意,特殊的数值NaN与任何值都不相等,包括它自己(即, NaN === NaNNaN == NaN 都是 false )。如果想测试某个数字是否为NaN,可以使用内置函数isNaN:如果x是NaN, isNaN(x) 会返回 true ,反之返回 false

还记得在JavaScript中,所有的数字都是双精度的吗?因为双精度都是近似值(这是不可避免的),所以对其进行比较时会遇到一些令人讨厌的意外情况。

如果比较的是整数(在 Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER 之间,包括两端的值),就可以放心地使用数字本身做比较。如果比较的是小数,最好使用关系运算符来测试它是否足够接近目标值。怎样才是足够接近呢?这其实取决于应用。JavaScript中存在一个数值常量, Number.EPSILON 。这个值非常小(大约是 2.22e-16 ),它通常代表在需要考虑两个数字差别时的差异程度。看看下面的例子:

let n = 0;
while(true) {
    n += 0.1;
    if(n === 0.3) break;
}
console.log('Stopped at ${n}');

运行这段代码,结果可能会让人非常惊讶:while循环跳过了0.3,无限地执行下去了。这是为什么呢?众所周知,0.1并不能精确地表示一个双精度数值,它介于两个二进制小数之间。所以循环执行到第三次时,n的值为 0.30000000000000004 ,判断条件返回fasle,结束循环唯一的机会就这样消失了。

可以使用Number.EPSILON重写上面的循环,此时关系运算符可以让比较“更缓和”,从而成功跳出循环:

let n = 0;
while(true) {
    n += 0.1;
    if(Math.abs(n - 0.3) < Number.EPSILON) break;
}
console.log('Stopped at ${n}');

注意,用数字n减去目标(0.3),然后取绝对值(使用 Math.abs ,第16章会讲解它)。还可以在这里做一个更简单的计算(比如,仅仅判断n是否大于0.3),不过取绝对值来比较两个值是否足够接近是测试两个双精度数值是否相等的通用方法。