3

我正在使用此代码来尝试找出一个数字中有多少位。下面的十六进制数字已打开所有位。

for (var i = 0x1FFFFFFFFFFFFF, m = 0; i & 1; ++m, i >>>= 1);

出于某种原因,打印m给出了 32,但在 SO 帖子中,我阅读了以下内容:

JavaScript 中的所有数字实际上都是符合 IEEE-754 的浮点双精度数。它们有一个 53 位尾数,这意味着任何大小约为 9 万亿或更小的整数值都将被准确表示。

除非我错误地实现了这一点,否则我不明白为什么m在应该有 53 位的情况下打印会给出 32。有人可以解释一下吗?

4

3 回答 3

6

JavaScript/ECMAScript 标准指定按位运算将数字截断为 31 位(向零舍入,取模数为 2 32,并将最高有效位解释为二进制补码符号),然后再发生其他任何事情。因此,您需要使用简单的算术对其进行重新编码。

这部分是因为处理小数的 FPU 可能无法在逻辑电路级别实现按位运算。

最幼稚的测试方法是for ( var i = 0; i != i + 1; ++ i ) ;,当我尝试它时,它使 Firefox 崩溃。(期待超时,但不!)稍微更具体的单线

for ( var i = 1, j = 0; i != i + 1; i *= 2, ++ j ) ;

确实产量j == 53

顺便说一句,请注意x | 0四舍五入的习语不适用于大于或等于 2 31的数字。所以Math.round一般比较好。

于 2013-03-22T00:07:20.687 回答
5

按位运算作为>>>32 位数字的工作,因此i实际上转换为 32 位。有关更多信息,请参阅

规格

产生式 ShiftExpression : ShiftExpression >>> AdditiveExpression 的评估如下:

无符号右移运算符 ( >>> )

  1. 令 lref 为评估 ShiftExpression 的结果。
  2. 令 lval 为 GetValue(lref)。
  3. 令 rref 为 AdditiveExpression 求值的结果。
  4. 设 rval 为 GetValue(rref)。
  5. 令 lnum 为ToUint32(lval)
  6. 设 rnum 为ToUint32(rval)
  7. 令 shiftCount 为屏蔽掉除 rnum 的最低有效 5 位之外的所有结果,即计算 rnum & 0x1F。
  8. 通过 shiftCount 位返回执行 lnum 的零填充右移的结果。空出的位用零填充。结果是一个无符号的 32 位整数。
于 2013-03-22T00:04:59.037 回答
0

Javascript 中的位运算符适用于 32 位整数。

这意味着将浮点数i转换为 32 位整数以用于移位操作,其余位将被丢弃。

参考:https ://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators

“所有按位运算符的操作数都转换为有符号的 32 位整数”

于 2013-03-22T00:06:20.147 回答