web-dev-qa-db-ja.com

>>>と>>の違い

Javaの演算子>>>>>の違いは何ですか?

334
Vipul

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

算術シフトでは、符号ビットは数の符号を保持するために拡張されます。

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

367
danben

>>>は符号なしシフトです。 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が加算されます。

関連する質問

91

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

のドキュメントから

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

46
Matt

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

38
corsiKa

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

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

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

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

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

ビットが2の補数表現の数値の場合、算術右シフトは2の累乗で除算する効果があります。これは、左端のビットが符号ビットなので機能します。 2のべき乗で割ると、符号は同じになります。

36
andru

ビット演算子とビットシフト演算子 についてもっと読む

>>      Signed right shift
>>>     Unsigned right shift

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

>>の後の左端の位置は符号の拡張子によって異なります。

簡単に言うと、>>>は常にzeroを左端の位置にシフトします に対して>>は、負の数の場合は1、正の数の場合は0です。


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

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
9
Braj

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

-1 (in 32-bit): 11111111111111111111111111111111

>>> 1操作の後になります:

2147483647: 01111111111111111111111111111111

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

-2 (in 32-bit): 11111111111111111111111111111110

>> 1操作の後になります:

-1: 11111111111111111111111111111111
5
bigT