web-dev-qa-db-ja.com

javaで「>>>」とはどういう意味ですか?

[〜#〜] so [〜#〜] 投稿で重複を見つけるためにこのコードを見つけました。しかし、この行がint mid = (low + high) >>> 1;の意味を理解していない

private static int findDuplicate(int[] array) {
        int low = 0;
        int high = array.length - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            System.out.println(mid);
            int midVal = array[mid];

            if (midVal == mid)
                low = mid + 1;
            else
                high = mid - 1;
        }
        return high;
    }
29
eagertoLearn

>>>演算子は Javaの符号なし右ビットシフト演算子 です。これは、オペランドを2で正しいオペランドのべき乗、またはここで2で効果的に分割します。

>>>>>の違いは、負の数をシフトするときにのみ現れます。 >>演算子は、1であった場合に1ビットを最上位ビットにシフトし、>>>0に関係なくシフトします。

UPDATE:

12147483647Integer.MAX_VALUE)を平均してみましょう。簡単に計算できます:

(1 + 2147483647) / 2 = 2147483648 / 2 = 1073741824

さて、コード(low + high) / 2で、これらは関係するビットです:

          1: 00000000 00000000 00000000 00000001
+2147483647: 01111111 11111111 11111111 11111111
================================================
-2147483648: 10000000 00000000 00000000 00000000  // Overflow
/2
================================================
-1073741824: 11000000 00000000 00000000 00000000  // Signed divide, same as >> 1.

>>>に「シフト」してみましょう:

          1: 00000000 00000000 00000000 00000001
+2147483647: 01111111 11111111 11111111 11111111
================================================
-2147483648: 10000000 00000000 00000000 00000000  // Overflow
>>> 1
================================================
+1073741824: 01000000 00000000 00000000 00000000  // Unsigned shift right.
71
rgettman

の意義

int mid = (low + high) >>> 1;

は符号なしシフトを使用することにより、負の数になるオーバーフローを回避します。 Javaはunsigned int値をサポートしていません。(BTW charは符号なし)として必要です。

これを書く伝統的な方法は

int mid = (low + high) / 2; // don't do this

ただし、これはより大きな合計でオーバーフローする可能性があり、中程度の負の数を取得します。

例えば.

int high = 2100000000;
int low = 2000000000;
System.out.println("mid using >>> 1 = " + ((low + high) >>> 1));
System.out.println("mid using / 2   = " + ((low + high) / 2));

プリント

mid using >>> 1 = 2050000000
mid using / 2   = -97483648

明らかに、2番目の結果は正しくありません。

35
Peter Lawrey

そのビット単位の演算子..ビット値に作用します。 Aが60を保持している場合、A >>> 2が15を与えると仮定します(ビット値0000 1111)

その実際の名前は「Shift Zero right Operator」です。ここでは、左オペランド値は右オペランドによって指定されたビット数(この場合は2)だけ右に移動され、シフトされた値はゼロ(0000)で埋められます。

2
Subhranshu