为什么这个代码为数字中的位(而不是53)提供32?

时间:2013-03-22 00:03:51

标签: javascript

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

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

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

  

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

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

3 个答案:

答案 0 :(得分: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通常更好。

答案 1 :(得分:5)

按位操作>>>对32位数进行处理,因此i实际转换为32位。有关详细信息,请参阅this

来自speficication

生产ShiftExpression:ShiftExpression>>> AdditiveExpression的计算方法如下:

  

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

     
      
  1. 让lref成为评估ShiftExpression的结果。
  2.   
  3. 让lval成为GetValue(lref)。
  4.   
  5. 让rref成为评估AdditiveExpression的结果。
  6.   
  7. 让rval为GetValue(rref)。
  8.   
  9. 让lnum ToUint32(lval)
  10.   
  11. 让rnum ToUint32(rval)
  12.   
  13. 让shiftCount成为屏蔽除rnum的最低有效5位之外的所有位的结果,即计算rnum&为0x1F。
  14.   
  15. 返回通过shiftCount位执行lnum的零填充右移的结果。空位用零填充。结果是无符号的32位整数。
  16.   

答案 2 :(得分:0)

Javascript中的按位运算符可以处理32位整数。

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

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

  

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