3

このコードを使用して、数値に含まれるビット数を調べようとしています。以下の 16 進数では、すべてのビットがオンになっています。

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

何らかの理由で印刷mすると32になりますが、SOの投稿で次のように読みました:

JavaScript のすべての数値は、実際には IEEE-754 準拠の浮動小数点 double です。これらには 53 ビットの仮数部があり、約 9000 兆以下の大きさの整数値が正確に表現されることを意味します。

mこれを間違って実装していない限り、 53 ビットであるはずの印刷が 32 ビットになる理由がわかりません。誰か説明してくれませんか?

4

3 に答える 3

6

JavaScript/ECMAScript 標準では、何かが起こる前に数値を 31 ビットに切り捨てる (ゼロに向かって丸め、モジュラスを 2 32で取り、最上位ビットを 2 の補数符号として解釈する) ように指定されています。したがって、単純な算術演算を使用して再コーディングする必要があります。

これは、小数を処理する FPU が論理回路レベルでビット単位の演算を実装していない可能性があるためです。

テストの最も単純な方法は、for ( var i = 0; i != i + 1; ++ i ) ;試してみると Firefox がクラッシュしたことです。(タイムアウトを予期していましたが、違います!) もう少し具体的なワンライナー

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

お譲り致しj == 53ます。

余談ですが、丸めのイディオムは 2 31x | 0以上の数値では機能しないことに注意してください。そのため、一般的には優れています。Math.round

于 2013-03-22T00:07:20.687 に答える
5

>>>32ビットの数値で動作するビット単位の操作なのでi、実際には32ビットに変換されます。詳細については、これを参照してください。

仕様から:

プロダクション ShiftExpression : ShiftExpression >>> AdditiveExpression は次のように評価されます。

符号なし右シフト演算子 ( >>> )

  1. ShiftExpression を評価した結果を lref とします。
  2. lval を GetValue(lref) とします。
  3. AdditiveExpression を評価した結果を rref とする。
  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 ビット整数で機能します。

これは、 の浮動小数点数がi32 ビット整数に変換されてシフト演算に使用され、残りのビットが破棄されることを意味します。

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

「すべてのビット演算子のオペランドは、符号付き 32 ビット整数に変換されます」

于 2013-03-22T00:06:20.147 に答える