web-dev-qa-db-ja.com

ビット単位のシフト演算子。署名付きと署名なし

私はインターネットからのクラムノートを使用してSCJP試験の練習をしています。

私のメモによると、>>演算子は右シフトで署名され、符号ビットは左から取り込まれることになっています。一方、左シフト演算子<<は符号ビットを保持することになっています。

ただし、遊んでみると、<<演算子を使用して符号をシフトできます(つまり、Integer.MAX_VALUE << 1-2に評価されますが、>>演算子を使用して符号をシフトすることはできません。

私はここで何かを誤解しているに違いありませんが、何ですか?

19
user271052

「>>」はサインを保持しているのでサインされています。数値の2進表現の左端の桁をフィラーとして使用します。例えば:

    | this value is used as a filler 
    11011011 
 >> 11101101  

    01010010
 >> 00101001 

">>>"はこの演算子の署名されていないバージョンです。常にゼロをフィラーとして使用します。

    11011011 
>>> 01101101  

    01010010
>>> 00101001

2進表現では、左端の桁が数値の符号を決定します。したがって、「1」の場合は負の値になり、「0」の場合は正の数になります。そのため、左端の数字をフィラーとして使用すると、記号を永続的に保つことができます。

44
Roman

シフトの背後にある考え方は、2の累乗で乗算および除算として機能できるということです(<< 1は* = 2に相当し、>> 2は/ = 4に相当します)。これが、符号付きバージョンのシフトが存在する理由です。ただし、符号なしシフトは必ずしもネガティブを保持しません。あなたが示唆するように、<<演算子は実際には符号を保持しません。それは単にあなたの例で起こります。 2,147,483,647で左シフトを試してください。それは前向きなままではありません。彼らがわざわざ「符号付き」の左シフトを行おうとしない理由は、数値が正から負(またはその逆)にシフトした場合、とにかく変数タイプの境界を超えたためです。

2
Jacob Zimmerman