>>ist arithmetische Verschiebung nach rechts, >>>ist logische Verschiebung nach rechts.
Bei einer arithmetischen Verschiebung wird das Vorzeichenbit erweitert, um die Vorzeichen der Zahl zu erhalten.
Zum Beispiel: -2 in 8 Bits dargestellt wäre 11111110(weil das höchstwertige Bit ein negatives Gewicht hat). Wenn Sie es mit der arithmetischen Verschiebung um ein Bit nach rechts verschieben, erhalten Sie 11111111oder -1. Die logische Rechtsverschiebung kümmert sich jedoch nicht darum, dass der Wert möglicherweise eine vorzeichenbehaftete Zahl darstellt. es verschiebt einfach alles nach rechts und füllt von links mit 0s. Eine Verschiebung unserer -2 um ein Bit nach rechts durch logische Verschiebung würde ergeben 01111111.
Obwohl ich zustimme und zu schätzen weiß, dass arithmetische Verschiebungen verwendet werden können, um vorzeichenbehaftete Zahlen mit zu multiplizieren 2^k, finde ich es seltsam, dass dies die Antwort aller ist. Eine Bitfolge ist keine Zahl und >>kann immer für jede Bitfolge verwendet werden: Sie macht immer das Gleiche, unabhängig von der Rolle, die die Bitfolge spielt, und unabhängig davon, ob sie ein Vorzeichenkonzept hat. Wäre es in Ordnung, Ihre bereits gute Antwort mit einer Diskussion des Falls zu erweitern, wenn Ihr Operand nicht als signierte Nummer interpretiert wird? Ist meine Beschwerde sinnvoll?
Ziggy
11
Warum sagen Sie, dass eine Bitfolge keine Zahl ist? Würden Sie sagen, dass eine Folge von Dezimalstellen keine Zahl ist?
Danben
4
@danben Die Diskussion, ob es sich um eine Zahl handelt oder nicht, ist nur dann sinnvoll, wenn Sie sie mit einem Kontext verknüpfen. Wenn das Internet nur Strom ist, stimme ich zu, dass ein String nur eine Zahl ist.
Bvdb
1
@danben aber eigentlich denke ich, worauf Ziggy sich wirklich bezog (imho), ist, dass a Stringauch als a angesehen werden könnte char[]. Er sagt nicht, dass a charkeine Zahl ist; Er sagt nur, dass es eine vorzeichenlose Nummer ist. Ich denke, dort ist er verloren.
Bvdb
5
@Ziggy ist richtig: Nicht jede Bitfolge ist eine Zahl, und nicht jede Folge von Dezimalstellen ist eine Zahl. Zum Beispiel: Telefonnummern, Postleitzahlen (in vielen Ländern) usw. sind Dezimalstellen, aber es ist nicht sinnvoll, sie zu addieren, zu subtrahieren oder zu multiplizieren, sodass es sich nicht wirklich um Zahlen handelt. Sie sind zufällig Zeichenfolgen mit Dezimalstellen, sollten jedoch als Zeichenfolgen behandelt werden. (Postleitzahlen in Kanada und Großbritannien enthalten Buchstaben und Ziffern.)
jcsahnwaldt sagt GoFundMonica
102
>>>ist unsigned-shift; es wird 0 einfügen >>ist signiert und erweitert das Vorzeichenbit.
Der Wert von n>>sist nrechtsverschobene sBitpositionen mit Vorzeichenerweiterung .
Der Wert von n>>>sist nrechtsverschobene sBitpositionen mit Null-Erweiterung .
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"
Um die Dinge klarer zu machen, fügen Sie ein positives Gegenstück hinzu
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"
Da es positiv ist, addieren sowohl vorzeichenbehaftete als auch vorzeichenlose Verschiebungen 0 zum Bit ganz links.
Der vorzeichenlose Rechtsverschiebungsoperator ">>>" verschiebt eine Null in die Position ganz links, während die Position ganz links nach ">>" von der Vorzeichenerweiterung abhängt.
Ich denke auch, dass Sie ein Beispiel geben sollten.
Bis zum
Ich nehme an, das >>>ist nicht signiert, aber warum 7>>32=7? Ich lief eine Schleife, die jeweils eine Schicht machte, und sah, dass es nach den 32Schichten wieder zu kam 7. Dies kann nur sinnvoll sein, wenn für jede herausgeschobene Zahl ein "äußerer Kreis" eingegeben wird. Nach den 32Schichten erreichte es irgendwie wieder seine Position, aber das macht natürlich immer noch keinen Sinn. Was ist los?
Ian Limarta
@ IanLimarta Nicht? Ich bekomme nur 0. ( for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));) Wenn Sie meinen, warum >>32selbst der ursprüngliche Wert zurückgegeben wird, sehen Sie dies .
Moira
Es tut mir Leid. Ich meinte, warum ist '7 >>> 32 = 7'.
Ian Limarta
40
Die logische Rechtsverschiebung ( v >>> n) gibt einen Wert zurück, bei dem die Bits vum nBitpositionen nach rechts verschoben wurden und Nullen von der linken Seite verschoben werden. Ziehen Sie in Betracht, 8-Bit-Werte zu verschieben, die binär geschrieben sind:
01111111>>>2=0001111110000000>>>2=00100000
Wenn wir die Bits als vorzeichenlose nichtnegative Ganzzahl interpretieren, hat die logische Rechtsverschiebung den Effekt, dass die Zahl durch die entsprechende Potenz von 2 geteilt wird. Wenn die Zahl jedoch in Zweierkomplementdarstellung vorliegt, teilt die logische Rechtsverschiebung negative Zahlen nicht korrekt . Zum Beispiel verschiebt sich die zweite Verschiebung nach rechts oben von 128 nach 32, wenn die Bits als vorzeichenlose Zahlen interpretiert werden. Aber es verschiebt sich -128 zu 32, wenn, wie es in Java typisch ist, die Bits im Zweierkomplement interpretiert werden.
Wenn Sie also verschieben, um durch eine Zweierpotenz zu teilen, möchten Sie die arithmetische Rechtsverschiebung ( v >> n). Es gibt einen Wert zurück, bei dem die Bits vum nBitpositionen nach rechts verschoben wurden und Kopien des am weitesten links liegenden Bits von v von der linken Seite verschoben werden:
01111111>>2=0001111110000000>>2=11100000
Wenn die Bits eine Zahl in Zweierkomplementdarstellung sind, hat die arithmetische Rechtsverschiebung den Effekt, durch eine Zweierpotenz zu teilen. Dies funktioniert, weil das Bit ganz links das Vorzeichenbit ist. Das Teilen durch eine Zweierpotenz muss das Zeichen gleich halten.
Das Bitmuster wird durch den linken Operanden und die Anzahl der zu verschiebenden Positionen durch den rechten Operanden angegeben. Der vorzeichenlose Rechtsschieber >>>verschiebt eine Null in die Position ganz links .
während die Position ganz links danach >>von der Zeichenverlängerung abhängt.
In einfachen Worten verschiebt sich>>> immer eine Null in die Position ganz links, während sich >>Verschiebungen basierend auf dem Vorzeichen der Zahl, dh 1 für negative Zahl und 0 für positive Zahl, verschieben.
Versuchen Sie es beispielsweise mit negativen und positiven Zahlen.
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));
Vielen Dank. Ich möchte nur einen Kommentar hinzufügen, um auf die Bitdarstellung für Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, 1 zu verweisen . zB : 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
Andy Dong
6
Der logische Operator >>> Nfür die Rechtsverschiebung ( ) verschiebt die Bits um N Positionen nach rechts, verwirft das Vorzeichenbit und füllt die N Bits ganz links mit Nullen auf. Zum Beispiel:
-1(in 32-bit):11111111111111111111111111111111
nach einer >>> 1Operation wird:
2147483647:01111111111111111111111111111111
Der rechtsverschobene arithmetische Operator ( >> N) verschiebt die Bits ebenfalls um N Positionen nach rechts, behält jedoch das Vorzeichenbit bei und füllt die N am weitesten links liegenden Bits mit Einsen auf. Zum Beispiel:
Antworten:
>>
ist arithmetische Verschiebung nach rechts,>>>
ist logische Verschiebung nach rechts.Bei einer arithmetischen Verschiebung wird das Vorzeichenbit erweitert, um die Vorzeichen der Zahl zu erhalten.
Zum Beispiel: -2 in 8 Bits dargestellt wäre
11111110
(weil das höchstwertige Bit ein negatives Gewicht hat). Wenn Sie es mit der arithmetischen Verschiebung um ein Bit nach rechts verschieben, erhalten Sie11111111
oder -1. Die logische Rechtsverschiebung kümmert sich jedoch nicht darum, dass der Wert möglicherweise eine vorzeichenbehaftete Zahl darstellt. es verschiebt einfach alles nach rechts und füllt von links mit 0s. Eine Verschiebung unserer -2 um ein Bit nach rechts durch logische Verschiebung würde ergeben01111111
.quelle
2^k
, finde ich es seltsam, dass dies die Antwort aller ist. Eine Bitfolge ist keine Zahl und>>
kann immer für jede Bitfolge verwendet werden: Sie macht immer das Gleiche, unabhängig von der Rolle, die die Bitfolge spielt, und unabhängig davon, ob sie ein Vorzeichenkonzept hat. Wäre es in Ordnung, Ihre bereits gute Antwort mit einer Diskussion des Falls zu erweitern, wenn Ihr Operand nicht als signierte Nummer interpretiert wird? Ist meine Beschwerde sinnvoll?String
auch als a angesehen werden könntechar[]
. Er sagt nicht, dass achar
keine Zahl ist; Er sagt nur, dass es eine vorzeichenlose Nummer ist. Ich denke, dort ist er verloren.>>>
ist unsigned-shift; es wird 0 einfügen>>
ist signiert und erweitert das Vorzeichenbit.JLS 15.19 Schichtarbeiter
Um die Dinge klarer zu machen, fügen Sie ein positives Gegenstück hinzu
Da es positiv ist, addieren sowohl vorzeichenbehaftete als auch vorzeichenlose Verschiebungen 0 zum Bit ganz links.
Verwandte Fragen
1 >>> 32 == 1
quelle
Sie sind beide rechtsverschoben, aber es
>>>
istunsigned
Aus der Dokumentation :
quelle
>>>
ist nicht signiert, aber warum7>>32=7
? Ich lief eine Schleife, die jeweils eine Schicht machte, und sah, dass es nach den32
Schichten wieder zu kam7
. Dies kann nur sinnvoll sein, wenn für jede herausgeschobene Zahl ein "äußerer Kreis" eingegeben wird. Nach den32
Schichten erreichte es irgendwie wieder seine Position, aber das macht natürlich immer noch keinen Sinn. Was ist los?for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));
) Wenn Sie meinen, warum>>32
selbst der ursprüngliche Wert zurückgegeben wird, sehen Sie dies .Die logische Rechtsverschiebung (
v >>> n
) gibt einen Wert zurück, bei dem die Bitsv
umn
Bitpositionen nach rechts verschoben wurden und Nullen von der linken Seite verschoben werden. Ziehen Sie in Betracht, 8-Bit-Werte zu verschieben, die binär geschrieben sind:Wenn wir die Bits als vorzeichenlose nichtnegative Ganzzahl interpretieren, hat die logische Rechtsverschiebung den Effekt, dass die Zahl durch die entsprechende Potenz von 2 geteilt wird. Wenn die Zahl jedoch in Zweierkomplementdarstellung vorliegt, teilt die logische Rechtsverschiebung negative Zahlen nicht korrekt . Zum Beispiel verschiebt sich die zweite Verschiebung nach rechts oben von 128 nach 32, wenn die Bits als vorzeichenlose Zahlen interpretiert werden. Aber es verschiebt sich -128 zu 32, wenn, wie es in Java typisch ist, die Bits im Zweierkomplement interpretiert werden.
Wenn Sie also verschieben, um durch eine Zweierpotenz zu teilen, möchten Sie die arithmetische Rechtsverschiebung (
v >> n
). Es gibt einen Wert zurück, bei dem die Bitsv
umn
Bitpositionen nach rechts verschoben wurden und Kopien des am weitesten links liegenden Bits von v von der linken Seite verschoben werden:Wenn die Bits eine Zahl in Zweierkomplementdarstellung sind, hat die arithmetische Rechtsverschiebung den Effekt, durch eine Zweierpotenz zu teilen. Dies funktioniert, weil das Bit ganz links das Vorzeichenbit ist. Das Teilen durch eine Zweierpotenz muss das Zeichen gleich halten.
quelle
>>>
setzt immer eine 0 in das Bit ganz links, während>>
eine 1 oder eine 0 gesetzt wird, je nachdem, welches Vorzeichen es hat.quelle
Lesen Sie mehr über Bitwise- und Bit Shift-Operatoren
Das Bitmuster wird durch den linken Operanden und die Anzahl der zu verschiebenden Positionen durch den rechten Operanden angegeben. Der vorzeichenlose Rechtsschieber
>>>
verschiebt eine Null in die Position ganz links .während die Position ganz links danach
>>
von der Zeichenverlängerung abhängt.In einfachen Worten verschiebt sich
>>>
immer eine Null in die Position ganz links, während sich>>
Verschiebungen basierend auf dem Vorzeichen der Zahl, dh 1 für negative Zahl und 0 für positive Zahl, verschieben.Versuchen Sie es beispielsweise mit negativen und positiven Zahlen.
Ausgabe:
quelle
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
Der logische Operator
>>> N
für die Rechtsverschiebung ( ) verschiebt die Bits um N Positionen nach rechts, verwirft das Vorzeichenbit und füllt die N Bits ganz links mit Nullen auf. Zum Beispiel:nach einer
>>> 1
Operation wird:Der rechtsverschobene arithmetische Operator (
>> N
) verschiebt die Bits ebenfalls um N Positionen nach rechts, behält jedoch das Vorzeichenbit bei und füllt die N am weitesten links liegenden Bits mit Einsen auf. Zum Beispiel:nach einer
>> 1
Operation wird:quelle