为什么右移右数有时会导致负数?

时间:2019-07-03 08:53:56

标签: javascript binary bit-manipulation bitwise-operators

在javascript中右移数字有时会导致负数。背后的原因是什么?可以缓解吗?

const now = 1562143596806 // UNIX timestamp in milliseconds
console.log(now >> 8) // -4783199

2 个答案:

答案 0 :(得分:3)

使用zero-fill right shift运算符(>>>)总是得到肯定的结果:

const now = 1562143596806 // UNIX timestamp in milliseconds
console.log(now >>> 8)

>>运算符返回数字的原因是由于该数字最初在内部以64-bit floating point number表示:

10110101110110111000000111010000100000110

移位操作首先将操作数转换为32位整数。通过仅保留32个最低有效位并丢弃其余位来实现此目的:

10110111000000111010000100000110

然后它将在保持符号的同时将其移位指定数量的位,即从左侧移8 1位:

11111111101101110000001110100001

转换回十进制,得出:

-4783199

答案 1 :(得分:1)

基本问题是1562143596806太大而无法容纳32位。它可以表示为Number,但是在执行按位运算时,该值首先转换为32位整数,这意味着在移位之前 的“高位”已经被删除-高位因此,结果的位不会从原始值中填充,它们是该临时32位值的符号的副本(或者对于>>>,它们将为零,这并不是真正的改进)。根据输入的确切位模式,结果恰好是负数只是偶然,如果它是正数,那么它仍将是错误的正值。

可以安全地将如此大的值作为BigInt进行操作,但是缺少对此的支持。使用浮点算法可以工作,但需要格外小心。例如,您可以除以256并将结果取底,但是您不能使用常规的|0来去除小数部分,因为即使被256除后,该值仍然太大而无法容纳32位。也存在各种非内置的BigInt库来处理这种事情。