Odpowiedzi:
>>
jest przesunięciem arytmetycznym w prawo, >>>
jest przesunięciem logicznym w prawo.
W przesunięciu arytmetycznym bit znaku jest przedłużany w celu zachowania podpisu liczby.
Na przykład: -2 przedstawione w 8 bitach byłoby 11111110
(ponieważ najbardziej znaczący bit ma wagę ujemną). Przesunięcie go o jeden bit za pomocą przesunięcia arytmetycznego dałoby ci 11111111
, lub -1. Logiczne przesunięcie w prawo nie ma jednak znaczenia, że wartość może reprezentować liczbę ze znakiem; po prostu przesuwa wszystko w prawo i wypełnia od lewej zerami. Przesunięcie naszego -2 o jeden bit za pomocą logicznego przesunięcia dałoby 01111111
.
2^k
, wydaje mi się dziwne, że to odpowiedź wszystkich. Łańcuch bitów nie jest liczbą i >>
zawsze można go użyć na dowolnym łańcuchu bitów: zawsze robi to samo bez względu na rolę, jaką odgrywa łańcuch bitów i niezależnie od tego, czy ma pojęcie „znaku”. Czy byłoby dobrze, gdybyś udzielił już i tak doskonałej odpowiedzi, omawiając sprawę, gdy twój operand nie jest interpretowany jako liczba podpisana? Czy moja skarga ma sens?
String
można również uznać za char[]
. Nie mówi, że a char
nie jest liczbą; on tylko mówi, że jest to liczba bez znaku . Myślę, że tam zginął.
>>>
Przesunięcie jest niepodpisane; wstawi 0. >>
jest podpisany i rozszerzy bit znaku.
Operatory zmiany obejmują przesunięcie w lewo, przesunięcie w
<<
prawo ze znakiem>>
i przesunięcie w prawo bez znaku>>>
.Wartość
n>>s
ton
przesunięte w prawos
pozycje bitów z przedłużeniem znaku .Wartość
n>>>s
ton
przesunięte w prawos
pozycje bitów z rozszerzeniem zera .
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"
Aby wyjaśnić, dodając pozytywny odpowiednik
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"
Ponieważ jest to pozytywne, zarówno podpisane, jak i niepodpisane przesunięcia dodadzą 0 do lewego końca.
1 >>> 32 == 1
Oba są przesunięte w prawo, ale tak >>>
jestunsigned
Z dokumentacji :
Niepodpisany operator przesunięcia w prawo „>>>” przesuwa zero w skrajne lewe położenie, natomiast skrajne lewe położenie po „>>” zależy od rozszerzenia znaku.
>>>
to niepodpisane, ale dlaczego 7>>32=7
? Przebiegłem pętlę, która zmieniała się jedna po drugiej i zobaczyłem, że po 32
zmianie wrócił do 7
. Jedynym sposobem, który może to mieć sens, jest to, że dla każdej przesuniętej liczby wchodziła ona w „zewnętrzny krąg”. Po 32
zmianach w jakiś sposób wrócił do swojej pozycji, ale oczywiście to nadal nie ma sensu. Co się dzieje?
Logiczne przesunięcie w prawo ( v >>> n
) zwraca wartość, w której bity v
zostały przesunięte w prawo o n
pozycje bitów, a cyfry 0 są przesunięte z lewej strony. Rozważ przesunięcie wartości 8-bitowych zapisanych w systemie binarnym:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
Jeśli interpretujemy bity jako niepodpisaną nieujemną liczbę całkowitą, logiczne przesunięcie w prawo powoduje podzielenie liczby przez odpowiadającą jej potęgę 2. Jeśli jednak liczba jest reprezentowana przez uzupełnienie dwóch, logiczne przesunięcie w prawo nie dzieli poprawnie liczb ujemnych . Na przykład drugie przesunięcie w prawo powyżej przesuwa 128 do 32, gdy bity są interpretowane jako liczby bez znaku. Ale przesuwa się z -128 na 32, gdy, jak to jest typowe w Javie, bity są interpretowane jako uzupełnienie dwóch.
Dlatego jeśli przesuwasz się, aby podzielić przez potęgę dwóch, potrzebujesz arytmetycznego przesunięcia w prawo ( v >> n
). Zwraca wartość, w której bity v
zostały przesunięte w prawo o n
pozycje bitów, a kopie najbardziej lewego bitu v są przesunięte z lewej strony:
01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
Kiedy bity są liczbą w reprezentacji dwóch uzupełnień, arytmetyczne przesunięcie w prawo powoduje dzielenie przez potęgę dwóch. Działa to, ponieważ skrajnie lewy bit jest bitem znaku. Dzielenie przez potęgę dwóch musi zachować znak bez zmian.
Przeczytaj więcej o operatorach Bitwise i Bit Shift
>> Signed right shift
>>> Unsigned right shift
Wzór bitowy jest podawany przez lewy operand, a liczba pozycji do przesunięcia przez prawy operand. Niepodpisany prawy operator >>>
zmiany biegów przesuwa zero na skrajne lewe położenie ,
podczas gdy pozycja najbardziej po lewej >>
zależy od rozszerzenia znaku.
W prostych słowach >>>
zawsze przesuwa zero do skrajnej lewej pozycji, podczas gdy >>
przesuwa się na podstawie znaku liczby, tj. 1 dla liczby ujemnej i 0 dla liczby dodatniej.
Na przykład spróbuj z liczbami ujemnymi i dodatnimi.
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));
wynik:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0'))
; Integer.MAX_VALUE : 01111111111111111111111111111111;
Integer.MIN_VALUE : 10000000000000000000000000000000;
-1 : 11111111111111111111111111111111;
0 : 00000000000000000000000000000000;
1 : 00000000000000000000000000000001
Operator logiczny przesunięcia w prawo ( >>> N
) przesuwa bity w prawo o N pozycji, odrzucając bit znaku i dopełniając N bitów najbardziej w lewo zerami. Na przykład:
-1 (in 32-bit): 11111111111111111111111111111111
po >>> 1
operacji staje się:
2147483647: 01111111111111111111111111111111
Operator arytmetyczny z przesunięciem w prawo ( >> N
) również przesuwa bity w prawo o N pozycji, ale zachowuje bit znaku i wypełnia N bitów najbardziej w lewo za pomocą 1. Na przykład:
-2 (in 32-bit): 11111111111111111111111111111110
po >> 1
operacji staje się:
-1: 11111111111111111111111111111111