需要一个JavaScript/ecma262 ToInt32算法解释
Need for a JavaScript/ecma262 ToInt32 algorithm explanation
我想了解 JS 引擎如何将 JS 数字 (Float64) 转换为 32 位有符号整数。我读到可以使用按位或类似的方式将 64 位浮点数快速转换为 32 位带符号整数:
-8589934590 | 0 // which gives 2
我不明白2是从哪里来的。根据 spec,ToInt32 算法执行此操作(粗体文本是我的,不是规范的):
- 设数是? ToNumber(argument): -8589934590 已经是一个 Number
- 如果number为NaN, +0, -0, +∞, or -∞, return +0.: No
- 设int为与number同号且量级为floor(abs(number))的Number值:-8589934590已经是一个整数
- 令 int32bit 为 int 模 2³² 由于 2³² 为正,因此结果也应为正。在 JS 中,余数运算符使用左操作数的符号,因此在这种情况下(-8589934590 为负数)要获得模数,我们取反:
let int32bit = 8589934590 % 2**32 // 4294967294 which has 32 bit length 0b11111111111111111111111111111110
- 如果 int32bit ≥ 2³¹, return int32bit - 2³²;否则 return int32bit。 int32bit 小于 2³¹(因为它是负数),所以我使用
int32bit
等于 -2
(即使我们考虑 0b11111111111111111111111111111110
一个无符号整数,那么它大于 2³¹ 并且 int32bit - 2³² 仍然等于 -2
谁能解释一下,我是否正确理解了 ToInt32 算法和按位或运算符?
您的第 4 步错误。模数由规范定义为:
The notation “x modulo y” (y must be finite and nonzero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x-k = q × y for some integer q.
所以-8589934590是我们的x,2**32是我们的y,由此我们也知道k一定是正数。如果我们选择 q = -1,我们可以将方程求解为 k = -4294967294。然而,这 不是有效的解决方案 ,因为 k(负)与 y(正)的符号不同。如果我们选择 q = -2,我们得到 k = 2.
因此,对于负数 x 和正数 y,q * y 总是必须导致比 x 更小的数字 才能使 k 为正数。因此,如果我们将其转换为正数(就像您所做的那样),我们正在寻找 数字的较大倍数 而不是 较小的倍数 。例如。如果我们取 2 % 3,那就是 return 2 (2 - 2 = 3 * 0),而 -2 模 3 将 return 1 (-2 -1 = 3 * -1)。
我想了解 JS 引擎如何将 JS 数字 (Float64) 转换为 32 位有符号整数。我读到可以使用按位或类似的方式将 64 位浮点数快速转换为 32 位带符号整数:
-8589934590 | 0 // which gives 2
我不明白2是从哪里来的。根据 spec,ToInt32 算法执行此操作(粗体文本是我的,不是规范的):
- 设数是? ToNumber(argument): -8589934590 已经是一个 Number
- 如果number为NaN, +0, -0, +∞, or -∞, return +0.: No
- 设int为与number同号且量级为floor(abs(number))的Number值:-8589934590已经是一个整数
- 令 int32bit 为 int 模 2³² 由于 2³² 为正,因此结果也应为正。在 JS 中,余数运算符使用左操作数的符号,因此在这种情况下(-8589934590 为负数)要获得模数,我们取反:
let int32bit = 8589934590 % 2**32 // 4294967294 which has 32 bit length 0b11111111111111111111111111111110
- 如果 int32bit ≥ 2³¹, return int32bit - 2³²;否则 return int32bit。 int32bit 小于 2³¹(因为它是负数),所以我使用
int32bit
等于-2
(即使我们考虑0b11111111111111111111111111111110
一个无符号整数,那么它大于 2³¹ 并且 int32bit - 2³² 仍然等于-2
谁能解释一下,我是否正确理解了 ToInt32 算法和按位或运算符?
您的第 4 步错误。模数由规范定义为:
The notation “x modulo y” (y must be finite and nonzero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x-k = q × y for some integer q.
所以-8589934590是我们的x,2**32是我们的y,由此我们也知道k一定是正数。如果我们选择 q = -1,我们可以将方程求解为 k = -4294967294。然而,这 不是有效的解决方案 ,因为 k(负)与 y(正)的符号不同。如果我们选择 q = -2,我们得到 k = 2.
因此,对于负数 x 和正数 y,q * y 总是必须导致比 x 更小的数字 才能使 k 为正数。因此,如果我们将其转换为正数(就像您所做的那样),我们正在寻找 数字的较大倍数 而不是 较小的倍数 。例如。如果我们取 2 % 3,那就是 return 2 (2 - 2 = 3 * 0),而 -2 模 3 将 return 1 (-2 -1 = 3 * -1)。