2013-09-27 18 views
9

Znalazłem ten kod, aby znaleźć duplikaty w poście SO tutaj. ale ja nie rozumiem, co to znaczy linia int mid = (low + high) >>> 1;Co oznacza ">>>" w języku Java?

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; 
    } 
+2

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html – iamnotmaynard

Odpowiedz

33

Operator >>> jest unsigned right bit-shift operator in Java. Skutecznie dzieli operand przez 2 na moc prawego argumentu, lub tylko 2 tutaj.

Różnica między >> a >>> pojawiłaby się tylko przy przesuwaniu liczb ujemnych. Operator >> przesuwa bit o numerze 1 na najbardziej znaczący bit, jeśli był to 1, a >>> przesuwa się w stanie 0 niezależnie.

UPDATE:

Chodźmy średnia 1 i 2147483647 (Integer.MAX_VALUE). Możemy zrobić matematyki w prosty sposób:

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

Teraz, wraz z kodem (low + high)/2, są bity zaangażowane:

  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. 

Zróbmy "Shift" do >>>:

  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. 
+1

@ możesz zilustrować na przykładzie. to byłoby bardzo pomocne – eagertoLearn

+1

Dzięki za wspaniałą ilustrację.ale w tym przypadku '(niski + wysoki)/2' i' niski + wysoki >>> 1', w jaki sposób są one równoważne? – eagertoLearn

+1

W Javie nie są one równoważne w przypadku przepełnienia, jak to zilustrowałem. – rgettman

17

Znaczenie

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

jest; używając przesunięcia niepodpisanego, unika przepełnień, których wynikiem jest liczba ujemna. Jest to potrzebne, ponieważ Java nie obsługuje wartości unsigned int. (BTW char jest niepodpisany)

Tradycyjny sposób napisać ten był

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

jednak może to przepełnienie dla większych kwot i masz liczbę ujemną do połowy.

np.

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

drukuje

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

wyraźnie drugi wynik jest nieprawidłowy.

+1

+1; bardzo spostrzegawczy (i odpowiedni), by wskazać na niepodpisany charakter char. – Bathsheba

+0

@peter: jeśli wdrażam wyszukiwanie binarne, potrzebuję '(mid = low + high)/2', jak można tego uniknąć ?. – eagertoLearn

+0

@peter: czy możesz podać przykład pokazujący znaczenie '>>>' proszę – eagertoLearn

0

jest operatorem bitowym. Działa na wartości bitu. Załóżmy, że jeśli A posiada 60 to A >>> 2 da 15 (wartość bitową 0000 1111)

Jego rzeczywista nazwa jest „Shift Zero prawo operator” tutaj wartość left operandy jest przesuwany w prawo o liczbę bitów określoną (2 w tym przypadku) przez prawy argument i przesunięte wartości są wypełniane zerami (0000).