2011-07-27 4 views
9

BER圧縮整数のデコードを実装していますが、最近は大きな整数のビット演算に関するJavaScriptの動作が変わっています。大きな整数を使用したビット演算

例えば:

var a = 17516032;   // has 25 bits 
alert(a << 7)    // outputs -2052915200 
alert(a * 128)    // outputs 2242052096 
alert(2242052096 >> 16) // outputs -31325 
alert(2242052096/65536) // outputs 34211 

最初の回避策(代わりに、左シフトの乗算)が許容される一方で、第二はありません。

どうしてですか?どのようにそれに耐える?

+0

私は、部門が受け入れられない理由を疑ったことはありませんか? – Guffa

+0

@ Guffa私は、32ビット整数だけでなく、いくつかの一般的なアプローチが必要です。 –

+0

整数は除算が行われません。浮動小数点数で実行されるため、私はあなたの議論を理解していません。さらに、倍精度の浮動小数点数は53ビットの整数しか表現できないため、BERで圧縮された数値をデコードする必要はありません。 – Guffa

答えて

7

17516032は、2進数で00000001000010110100011000000000です。左に7移動すると10000101101000110000000000000000となります。これはのtwo's complement(これはほぼすべてのコンピュータが負の数を表す方法です)に相当します。

>>は符号付き右シフトです。これは、左端のビット(数値の符号を決定する)が左側にシフトされることを意味します。

1100 >> 2 == 1111 
0111 >> 2 == 0001 

あなたは(符号ビットを無視する)符号なしシフトを行いたい場合、ゼロ埋めれるビット列の左端を>>>を使用しています。

+0

それは、ありがとう!なぜ左シフトがそのような奇妙な結果を生むのか? –

+0

問題ありません。それを含めるために私の答えを編集しました。 – tskuzzy

3

ビット演算子は32ビット整数で動作し、乗算と除算は浮動小数点数で動作します。

数値をシフトすると、その数値は操作の前に浮動小数点数から32ビット整数に変換され、操作後に浮動小数点数に変換されます。 2242052096には32番目のビットが設定されているため、32ビット整数に変換したときは負の数になります。

>>右シフト演算子は値の符号を変更しません。つまり、左からシフトしたビットは符号ビットと同じ値を持ちます。 >>>右シフト演算子を使用して、代わりにゼロビットをシフトします。

参考:MDN: Bitwise operators

2

(2242052096/65536) == (2242052096 >>> 16)

は異なるシフトに注意してください。

1

Javascriptは通常、(倍精度)浮動小数点数を表します。

ほとんどすべてのビット演算は、符号付き32ビット整数に変換され、何をしようとしていても、変換後の符号付き32ビット整数として処理されます。

例外は、>>>です。変換後の結果は、の符号なしの32ビット整数として処理されます。

  • 右シフトは、単に>>>代わりの>>を使用して動作させることができ;:だから

  • a * 128は、最初に符号付き32ビット整数に変換されることはないため、期待される答えが得られます。これは単なる浮動小数点の乗算です。
  • a << 7は、符号付き32ビット整数に変換された後に1を符号ビットにシフトし、負の符号付き32ビット値になるため、予期しない応答を示します。

<<<ありませんが、あなたはシフトとして、あなたの左シフトを書きたいならば、あなたは

(a << 7) >>> 0 

が期待される答え(効果的>>> 0を取得するために使用できる署名キャスト32-ビット値を符号なし32ビット値に変換します)。

+0

ニース。説明をありがとう! –

関連する問題