问题描述
我试图了解JS引擎如何将JS编号(Float64)转换为32位带符号整数。我读到可以使用按位OR迅速将64位浮点数转换为32位有符号整数:
-8589934590 | 0 // which gives 2
我不明白2的来源。根据{{3}},ToInt32算法可以做到这一点(粗体字是我的,不是规范的):
- 让 number 是? ToNumber(参数): -8589934590已经是一个数字
- 如果 number 为NaN,+ 0,-0,+∞或-∞,则返回+0 。: 否
- 让 int 为与数字相同的符号,其大小为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³¹,则返回 int32bit -2³²;否则返回 int32bit 。 int32bit小于2³¹(因为它为负数),所以我使用
int32bit
等于-2
(即使我们考虑0b11111111111111111111111111111110
无符号整数,则它大于2³¹,而 int32bit -2³²仍等于-2
有人可以解释一下,我是否正确理解ToInt32算法和按位OR运算符?
解决方法
您的步骤4错误。规范将模数定义为:
符号“ x模y”(y必须是有限且非零)可计算与y(或零)具有相同符号的值k,使得abs(k)
因此-8589934590是我们的x,而2 ** 32是我们的y,由此我们也知道k必须为正。如果选择q = -1,则可以将方程求解为k = -4294967294。但是,这不是有效的解决方案,因为k(负数)与y(正数)的符号不同。如果选择q = -2,则得到k = 2。
因此,对于负数x和正数y,要使k为正数,q * y总是必须比x小 个数。因此,如果我们将其转换为正数(如您所做的那样),我们将寻找数字的较大倍数,而不是较小的 。例如。如果我们取2%3,则将返回2(2-2 = 3 * 0),而-2模3将返回1(-2 -1 = 3 * -1)。