考虑条件
(-1 - Number.EPSILON < -1) === (-2 - Number.EPSILON < -2)
此示例在我的计算机上的Chrome控制台中执行false
(?!),但我不知道为什么(左侧为true,右侧为false)。在Edge和Firefox中,整个条件也执行到false
,在Internet Explorer(??!?)中但执行到true
。
答案 0 :(得分:3)
浮点数以零为中心。也就是说,它们在0附近最密集;数字越大,数字线在该区域中存在的浮点数越少。
不良ASCII近似值:
---------------------------------------(-1)-----(0)-----(1)------------------------------------------
. . . . . . . . . . .................. . . . . . . . . . .
上一行代表实数;下面的点标记可能的浮点值。 -1和1之间有许多可能的浮点值,从而可以实现非常精细的区分。离0越远,可能的浮点值就越稀疏,这意味着以较低的精度存储较大的数字。
Number.EPSILON
是1与下一个较高的浮点数之间的距离。这意味着1 + Number.EPSILON
作为浮点值存在并且可以准确表示。同样适用于-1 - Number.EPSILON
,该值相同,但带有负号。
但是,2 + Number.EPSILON
不存在。因为1比2更接近0,所以浮点数在1周围比2周围更密集。特别是2与下一个较高的浮点值之间的差大于Number.EPSILON
(实际上,如果结果是2 * Number.EPSILON
,我不会感到惊讶。由于2 + Number.EPSILON
无法精确表示,因此将其舍入为最接近的浮点数,该数本身就是2:
console.log(2 + Number.EPSILON === 2); // true
对于Internet Explorer:does not support Number.EPSILON
,所以
-1 - Number.EPSILON < -1
被评估为
-1 - undefined < -1
即Number.NaN < -1
,其值(与涉及NaN
的所有比较一样)的计算结果为false
。
答案 1 :(得分:1)
JavaScript数字是双精度浮点数字(64位)。其中0-51位代表小数,其余位代表指数。
如果您尝试将Number.EPSILON
转换为二进制文件-您会发现它是:
> Number.EPSILON.toString(2)
'0.0000000000000000000000000000000000000000000000000001'
第一位是0
,因此,如果加1-它变为1,它仍然适合小数位:
> (1 + Number.EPSILON).toString(2)
'1.0000000000000000000000000000000000000000000000000001'
//---- So -----
(1+Number.EPSILON) !== 1
但是,当您添加2
(二进制10
)时,它会捕获到左侧的其他位-因此,右边的(不太重要的)位被切掉了,以适合小数位。
2 + Number.EPSILON
10.000000000000000000000000000000000000000000000000000|1 <- right bit dropped
^
51 bit
//---- So -----
(2+Number.EPSILON) === 2