ES6 在Number
對(duì)象上面,新增一個(gè)極小的常量Number.EPSILON
。根據(jù)規(guī)格,它表示 1 與大于 1 的最小浮點(diǎn)數(shù)之間的差淮野。
對(duì)于 64 位浮點(diǎn)數(shù)來(lái)說(shuō),大于 1 的最小浮點(diǎn)數(shù)相當(dāng)于二進(jìn)制的1.00..001
吹泡,小數(shù)點(diǎn)后面有連續(xù) 51 個(gè)零骤星。這個(gè)值減去 1 之后,就等于 2 的 -52 次方爆哑。
Number.EPSILON === Math.pow(2, -52)
// true
Number.EPSILON
// 2.220446049250313e-16
Number.EPSILON.toFixed(20)
// "0.00000000000000022204"
Number.EPSILON
實(shí)際上是 JavaScript 能夠表示的最小精度洞难。誤差如果小于這個(gè)值,就可以認(rèn)為已經(jīng)沒(méi)有意義了泪漂,即不存在誤差了廊营。
引入一個(gè)這么小的量的目的歪泳,在于為浮點(diǎn)數(shù)計(jì)算,設(shè)置一個(gè)誤差范圍露筒。我們知道浮點(diǎn)數(shù)計(jì)算是不精確的呐伞。
0.1 + 0.2
// 0.30000000000000004
0.1 + 0.2 - 0.3
// 5.551115123125783e-17
5.551115123125783e-17.toFixed(20)
// '0.00000000000000005551'
上面代碼解釋了,為什么比較0.1 + 0.2與0.3得到的結(jié)果是false慎式。
0.1 + 0.2 === 0.3 // false
Number.EPSILON
可以用來(lái)設(shè)置“能夠接受的誤差范圍”伶氢。比如,誤差范圍設(shè)為 2 的-50 次方(即Number.EPSILON * Math.pow(2, 2)
)瘪吏,即如果兩個(gè)浮點(diǎn)數(shù)的差小于這個(gè)值癣防,我們就認(rèn)為這兩個(gè)浮點(diǎn)數(shù)相等。
5.551115123125783e-17 < Number.EPSILON * Math.pow(2, 2)
// true
因此掌眠,Number.EPSILON
的實(shí)質(zhì)是一個(gè)可以接受的最小誤差范圍蕾盯。
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
0.1 + 0.2 === 0.3 // false
withinErrorMargin(0.1 + 0.2, 0.3) // true
1.1 + 1.3 === 2.4 // false
withinErrorMargin(1.1 + 1.3, 2.4) // true
上面的代碼為浮點(diǎn)數(shù)運(yùn)算,部署了一個(gè)誤差檢查函數(shù)蓝丙。