>>>と>>の違い


回答:


408

>>算術右シフト、>>>論理右シフトです。

算術シフトでは、符号ビットが拡張されて数値の符号が保持されます。

例:-2は8ビットで表されます11111110(最上位ビットは負の重みを持つため)。算術シフトを使用して1ビット右にシフトすると11111111、または-1になります。ただし、論理右シフトは、値が符号付きの数値を表す可能性があることを気にしません。すべてを右に移動し、左から0で埋めるだけです。当社-2右は論理シフトを与える使用してビットをシフト01111111


8
算術シフト使用して符号付き数値にを掛けることできることに同意し、感謝しますが2^k、これが全員の答えであることは奇妙だと思います。ビットの文字列は数値ではなく、>>常にビットの文字列で使用できます。ビットの文字列が果たす役割に関係なく、また「符号」の概念があるかどうかに関係なく、常に同じことを行います。オペランドが符号付き数として解釈されていない場合の議論で、すでに素晴らしい答えを拡張してもよいでしょうか?私の不満は理にかなっていますか?
Ziggy、

11
ビットの文字列は数値ではないと言うのはなぜですか?一連の10進数は数値ではないと思いますか?
danben 2014

4
@danben数値であるかどうかを議論することは、それをコンテキストにリンクする場合にのみ意味があります。インターネットが電気だけの場合、文字列は単なる数値であることに同意します。
bvdb 2015

1
@danben実際、私はジギーは本当に(私見)に参照のうえたものだと思う、ということであるStringとしても捉えることができましたchar[]。彼charはaが数ではないと言っているのではありません。彼はそれが符号なしの数だと言っているだけです。私はそれが彼を失った場所だと思います。
bvdb 2015

5
@Ziggyは正しいです。ビットのすべての文字列が数値であるとは限らず、10進数のすべてのシーケンスが数値であるとは限りません。例:電話番号、郵便番号(多くの国では)などは10進数の文字列ですが、それらを加算、減算、または乗算しても意味がないため、実際には番号ではありません。それらはたまたま10進数の文字列ですが、文字列として扱う必要があります。(カナダとイギリスの郵便番号には文字と数字が含まれています。)
jcsahnwaldtはGoFundMonicaを

102

>>>符号なしシフトです。これは0を挿入します>>。符号付きで、符号ビットを拡張します。

JLS 15.19シフト演算子

シフト演算子には、左シフト<<>>符号付き右シフト、符号なし右シフトがあり>>>ます。

n>>sであるn右シフトsとビット位置符号拡張

n>>>sであるn右シフトsとビット位置ゼロ拡張

    System.out.println(Integer.toBinaryString(-1));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >> 16));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >>> 16));
    // prints "1111111111111111"

肯定的な対応を追加して物事をより明確にする

System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"

正であるため、符号付きシフトと符号なしシフトの両方で、左端のビットに0が追加されます。

関連する質問


あなたの例がなければ、私はそれを得ることができません。
mr5

47

どちらも右シフトですが>>>unsigned

ドキュメントから:

符号なし右シフト演算子 ">>>"はゼロを左端の位置にシフトしますが、 ">>"の後の左端の位置は符号拡張に依存します。


12
例で説明できますか
Kasun Siyambalapitiya

1
また、例を挙げるべきだと思います。
byxor 16

それ>>>は署名されていないと思いますが、なぜ7>>32=7ですか?一度に1つのシフトを実行するループを実行したところ、32シフト後に、に戻ったことがわかりました7。これが意味を持つ唯一の方法は、シフトアウトされた各数値について、「外側の円」に入ったということです。32シフト後、それはなんとかその位置に戻ったが、明らかにそれはまだ意味をなさない。何が起こっている?
Ian Limarta 2017年

@IanLimartaそうじゃない?(0 for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));>>32それ自体が元の値を返す理由を意味する場合は、これを参照してください。
モイラ2017年

申し訳ありません。なぜ「7 >>> 32 = 7」なのかということです。
Ian Limarta 2017年

40

論理右シフト(v >>> n)は、のビットがビット位置だけv右にシフトされ、n0が左側からシフトインされた値を返します。バイナリで書かれた8ビット値をシフトすることを検討してください:

01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000

ビットを符号なしの非負整数として解釈する場合、論理右シフトは、数値を対応する2の累乗で除算する効果があります。ただし、数値が2の補数表現である場合、論理右シフトは負の数を正しく除算しません。 。たとえば、ビットが符号なしの数値として解釈されると、上の2番目の右シフトは128から32にシフトします。しかし、Javaで一般的なように、ビットが2の補数で解釈されると、-128から32にシフトします。

したがって、2の累乗で除算するためにシフトする場合は、算術右シフト(v >> n)が必要です。これは、inのビットがビット位置だけv右にシフトされた値を返し、vの左端のビットのnコピーが左側からシフトインされます。

01111111 >> 2 = 00011111
10000000 >> 2 = 11100000

ビットが2の補数表現の数値である場合、算術右シフトは2の累乗で除算する効果があります。左端のビットが符号ビットであるため、これは機能します。2の累乗で除算する場合は、符号を同じに保つ必要があります。


38

>>>常に左端のビットに0 >>を入れますが、その符号に応じて1または0を入れます。


10

ビット演算子とビットシフト演算子の詳細を読む

>>      Signed right shift
>>>     Unsigned right shift

ビットパターンは左側のオペランドで与えられ、シフトする位置の数は右側のオペランドで与えられます。符号なし右シフト演算子は>>> ゼロを左端の位置シフトします

左端の位置>>は符号拡張に依存します。

簡単な言葉で>>>常にシフトゼロを左端位置に、一方>>負の数と正の数の0の場合は1、すなわち数の符号に基づいてシフトします。


たとえば、正の数だけでなく負の数でも試してください。

int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));

System.out.println();

c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));

出力:

11111111111111111111111111011001
11111111111111111111111101100100
  111111111111111111111111011001
11111111111111111111111101100100

                          100110
                        10011000
                          100110
                        10011000

ありがとう。Integer.MAX_VALUE、Integer.MIN_VALUE、-1、0、1のビット表現を参照するコメントを追加したいだけです。例:System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0')); Integer.MAX_VALUE01111111111111111111111111111111; Integer.MIN_VALUE10000000000000000000000000000000; -111111111111111111111111111111111; 000000000000000000000000000000000; 100000000000000000000000000000001
Andy Dong

6

右シフト論理演算子(>>> N)は、ビットをN桁だけ右にシフトし、符号ビットを破棄し、左端のNビットに0を埋め込みます。例えば:

-1 (in 32-bit): 11111111111111111111111111111111

>>> 1操作後:

2147483647: 01111111111111111111111111111111

右シフト算術演算子(>> N)も、ビットをN桁だけ右にシフトしますが、符号ビットを保持し、左端のNビットに1を埋め込みます。例えば:

-2 (in 32-bit): 11111111111111111111111111111110

>> 1操作後:

-1: 11111111111111111111111111111111
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.