2016-03-29 4 views

Antwort

1

Ja, (low + high) >> 1 ausfließen kann, wenn die Summe hoch genug ist. Wie Sie wissen, ist >>> für unsigned, so dass es immer in 0 auf der wichtigsten Seite verschiebt. Dies erweist sich als sehr wichtig, falls es überläuft.

Der Trick, (low + high) sogar mit Überlauf zu verwenden, ist, dass Informationen noch behalten werden. Wenn es überläuft, ist die maximal mögliche mathematische Summe immer noch Integer.MAX_VALUE * 2, die immer noch als unsigned int dargestellt werden könnte, wenn Java eins hätte. Aber wir können behandeln die Summe als unsigned int beim Dividieren von 2 mit dem unsigned rechten Shift-Operator, >>>. Wenn Bit-Verschiebung nach rechts durch 1 erfolgt, können wir die Summe als unsigned behandeln int, "un-überläuft" die int.

Mit >> hier wird nicht funktionieren, wenn die Summe überläuft, weil sie in eine negative Zahl überläuft und >> wird in einem 1 verschieben, halten Sie den Wert negativ. Dies führt zu einer falschen Durchschnittsberechnung (2 positive Zahlen, deren Summenüberläufe zu einem negativen Durchschnitt führen).

Ob Sie >>> oder >> verwenden, Überlauf ist eine Möglichkeit. So können beide überlaufen. Aber nur >>> wird den Fall gut behandeln, die Summe "nicht überlaufen".

Der Trick

avg = (low & high) + ((low^high) >> 1); 

ist eine andere Art und Weise der Berechnung des Durchschnitts, wenn die Summe überlaufen kann. Dies vermeidet den Überlauf vollständig. Dies zerlegt die Summe in 2 Teile - die "Übertrag" -Bits und die "Nicht-Übertrag" -Bits.

Bei der Addition werden die Bits zum nächsten höherwertigen Bit übertragen, wenn beide Bits gesetzt sind - low & high. Normalerweise müssen diese Bits auch nach links verschoben werden, aber wir berechnen den Durchschnitt von 2 Zahlen, also würden wir am Ende auch richtig verschieben. Das Nettoergebnis: keine Verschiebung hier.

die Bits, die nicht ausgeführt werden, sind entweder ein 1 wenn die Bits verschieden oder ein 0 sind, wenn die Bits gleich sind - das ist, wo (low^high) aus (XOR) kommt. Normalerweise werden diese Bits nicht verschoben, aber wir berechnen den Durchschnitt von 2 Zahlen, also würden wir am Ende auch richtig verschieben. Diese Verschiebung erscheint als >> 1.Die & und ^ Operatoren überlaufen nicht, so >> wird hier gut funktionieren.

Beispiel: Durchschnitt von 1100 (12) und 1010 (10)

1100 & 1010 = 1000 
1100^1010 = 0110, 0110 >> 1 = 0011 
1000 + 0011 = 1011 (11)