为什么 JavaScript 中两个不同的数字相等?

2022-01-17 00:00:00 numbers javascript

我一直在玩 JavaScript 控制台,突然决定试试这个:

I've been messing around with a JavaScript console, when I suddenly decided to try this:

<代码> 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

令人惊讶的是,它们是相等的:

Surprisingly, they're equal:

为什么会这样?它们显然是不同的数字(即使 0xFFFF...FFFF 短了一位)

Why does it happen? They're clearly different numbers (even the 0xFFFF...FFFF is one digit shorter)

如果我将 F 添加到 0xFFFF...FF,它们不再相等:<代码> 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

If I add a F to the 0xFFFF...FF, they're not equal anymore: 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

这是预期的行为吗?

推荐答案

JavaScript 中的所有数字在内部由 64 位浮点数(参见 §4.3.19 规范).这意味着它可以精确地表示从 09007199254740992 的每个整数(十六进制值 0x20000000000000).任何大于它(或小于它的负数)的整数可能需要四舍五入到最接近的近似值.

All numbers in JavaScript are internally represented by 64-bit floating point numbers (see §4.3.19 of the specification). That means it can exactly represent every integer from 0 up to 9007199254740992 (hex value 0x20000000000000). Any integers greater than that (or less than it's negative counterpart) may need to be rounded to the closest approximate value.

观察:

9007199254740992 === 9007199254740993
> true

但是,四舍五入到足够不同的近似值的两个数字在比较它们时仍会得出不同的值.例如:

However, two numbers that are rounded to sufficiently different approximate values still evaluate to different values when you compare them. For example:

9007199254740992 === 9007199254740994
> false

这就是您在添加另一个 F 数字的第二个片段中看到的内容.

This is what you're seeing in the second snippet where you add another F digit.

注意:ECMAScript 规范现在定义了 Number.MAX_SAFE_INTEGER 作为一个全局常量,等于 9007199254740991.

Note: The ECMAScript specification now define Number.MAX_SAFE_INTEGER as a global constant equal to 9007199254740991.

相关文章