原因
二进制浮点数最大的问题(不仅JavaScript,所有遵循IEEE 754规范的语言都是如此),是会出现如下情况:
0.1 + 0.2 === 0.3; // false
从数学角度来说,上面的条件判断应该为true,可结果为什么是false呢?简单来说,二进制浮点数中的0.1和0.2并不是十分精确,它们相加的结果并非刚好等于0.3,而是一个比较接近的数字0.30000000000000004,所以条件判断结果为false。
判断两个数是否相等
最常见的方法是设置一个误差范围值,通常称为“机器精度”(machine epsilon), 对JavaScript的数字来说,这个值通常是2^-52 (2.220446049250313e-16)。从ES6开始,该值定义在Number.EPSILON中,我们可以直接拿来用,也可以为ES6之前的版本写
//polyfill:
if (!Number.EPSILON) {
Number.EPSILON = Math.pow(2,-52);
}
可以使用Number.EPSILON来比较两个数字是否相等(在指定的误差范围内)
function numbersCloseEnoughToEqual(n1,n2) {
return Math.abs( n1 - n2 ) < Number.EPSILON;
}
var a = 0.1 + 0.2;
var b = 0.3;
numbersCloseEnoughToEqual( a, b );//true
numbersCloseEnoughToEqual( 0.0000001, 0.0000002 );//false
能够呈现的最大浮点数大约是1.798e+308(这是一个相当大的数字),它定义在Number.MAX_VALUE中。最小浮点数定义在Number.MIN_VALUE中,大约是5e-324,它不是负数,但无限接近于0
使用math.js处理运算
判断是否是整数
ES6语法
Number.isInteger()
polyfill写法
if (!Number.isInteger) {
Number.isInteger = function(num) {
return typeof num == "number" && num % 1 == 0;
}
}
是否是安全的整数
Number.isSafeInteger()
判断是否是数字
首先需要理解:typeof NaN == "number"
ES6语法
Number.isNaN(123) // false
Number.isNaN("123") // false
Number.isNaN("abc") // false
Number.isNaN(1/"abc")// true
Number.isNaN(1/0) // false 因为1/0是Infinity正无穷大,还是数字类型
ES5写法
isNaN(123)//false
isNaN("123")//false
isNaN("abc")//true
isNaN(1/"abc")//true
isNaN(1/0)//false
还可以使用ES6语法:Object.is(num,NaN)
判断是否是有限值
isFinite()
判断被传入的参数值是否为一个有限数值(finite number)
isFinite()可能会把参数转为一个数字,Number.isFinite()不会把参数转为数值
如果参数是 NaN,正无穷大或者负无穷大,会返回false,其他返回 true。
示例
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(0); // true
isFinite("0"); // true
isFinite(1/0); // false
isFinite(null); // true
isFinite(undefined); // false
ES6语法
Number.isFinite()
Number.isFinite(0); // true
Number.isFinite("0"); // false
Number.isFinite(1/0); // false
Number.isFinite(null); // false
Number.isFinite(undefined); // false
总结
判断是否是非法数字使用Number.isNaN()
保证数字可运算使用Number.isFinite()