数字语法

本文最后更新于:38 分钟前

数字语法

比较小的数值

二进制浮点数最大的问题(不仅JavaScript,所有遵循IEEE 754规范的语言都是如此),是会出现如下情况:

1
0.1 +0.2 === 0.3;// false

从数学角度来说,上面的条件判断应该为 true,可结果为什么是false 呢?
简单来说,二进制浮点数中的0.1和0.2并不是十分精确,它们相加的结果并非刚好等于0.3,而是一个比较接近的数字0.30000000000000004,所以条件判断结果为false。
在处理带有小数的数字时需要特别注意。很多(也许是绝大多数)程序只需要处理整数,最大不超过百万或者万亿,此时使用JavaScript的数字类型是绝对安全的。

那么应该怎样来判断0.1 + 0.2和0.3是否相等呢?

最常见的方法是设置一个误差范围值,通常称为“机器精度”(machine epsilon),对JavaScript的数字来说,这个值通常是2^-52 (2.220446049250313e-16)。
从 ES6开始,该值定义在Nuwber .EPSILON中,我们可以直接拿来用,也可以为ES6之前的版本写polyfill:

1
2
3
if (!Number.EPSILON){	
Number.EPSILON = Math.pow(2,-52);
}

可以使用Number.EPSILON来比较两个数字是否相等(在指定的误差范围内):

1
2
3
4
5
6
7
8
9
10
11
12
13
let a=0.1+0.2
let b=0.3

a //0.30000000000000004
a==b //false

function numbersCloseEnoughToEqual(n1,n2) {
return Math.abs(n1-n2) < Number.EPSILON
}

numbersCloseEnoughToEqual(a,b)//true
numbersCloseEnoughToEqual(0.000000000001,0.000000000002)//false

能够呈现的最大浮点数大约是1.798e+308(这是一个相当大的数字),它定义在Number .MAX_VALUE中。最小浮点数定义在Number.MIN_VALUE中,大约是5e-324,它不是负数,但无限接近于0!

零值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0/3 //0
0/-3 //-0

3/0 //Infinity
-3/0 //NaN

let a=-3
a/0 //-Infinity

-0===0 //false
-0==0 //true

-0==-0 //false
-0===-0 //false

对负零进行字符串化会返回'0'

1
2
3
4
5
6
7
let a=0/-3

a //-0
a.toString() //'0'
a+'' //'0'
String(a) //'0'
JSON.stringify(a) //'0'

有意思的是,如果反过来将其从字符串转换为数字,得到的结果是准确的:

1
2
3
+'-0' //-0
Number('-0') //-0
JSON.parse('-0') //-0

要区分-0和0,需要做一些特殊处理

1
2
3
4
5
6
7
8
function isNegZero(n) {
n=Number(n)
return (n===0)&&(1/n===-Infinity)
}

isNegZero(-0) //true
isNegZero(0/-3) //true
isNegZero(0) //false

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!