Warum dieser code für addition(bitweise operation) funktioniert in java
public int add(int a, int b){
while (b != 0){
int carry = (a & b) ;
a = a ^ b;
b = carry << 1;
}
return a;
}
Dies ist der code zur Berechnung der Summe zweier ganzer zahlen bitweise operation.
Wenn ich die Berechnung manuell/programmgesteuert, ich sehe, es funktioniert für jede ganze Zahl.
Aber ich bin nicht in der Lage, um herauszufinden, jede Art von Beziehung zwischen Zwischenwert von a
und carry
.
und warum tragen ist, multipliziert mit 2 zuweisen b
?
PS: ich fand die Antworten hier
Bitweise Multiplizieren und Addieren in Java
aber das ist für die Multiplikation und nicht für neben.
- Haben Sie irgendwelche Kenntnisse über die bitweise addition?
- Die tragen eine Ziffer Hinzugefügt, um die nächste Stelle, natürlich. Dieser Algorithmus nur führt "- Zusatz, wie man Sie kennt aus der Schule", sondern ein bisschen Durcheinander, anstatt sorgfältig durch, Ziffer für Ziffer - es ist zudem ohne trägt erste (xor), dann fügt der Karies separat (wieder in der gleichen Weise), bis es nicht mehr trägt (so er fügt hinzu, die trägt-generated-by-adding-trägt, dann trägt generiert, die neben und so weiter). Diese beenden müssen, da führt nur gehen "nach Links" - also mindestens ein bit wird auf "fixed" nach jeder iteration.
- ja, habe ich, was ist dein Punkt trotzdem?
- vielen Dank..eigentlich war ich es hart finden, zu glauben, wie Sie tragen über nächste bit arbeitet Binär, wie es ist, nicht geschieht bit für bit aus starten..
- ich wollte erklären, wie es funktioniert und wollte wissen, auf welcher Ebene Sie sind. So wäre es einfacher gewesen, mir zu erklären (und nicht schreiben, Sachen, die Sie bereits kennen).
- ok, ich war nur zu finden es verwirrend, wie carry-Betrieb wird durchgeführt, indem mit Schleife..
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zunächst daran erinnern, außerdem in der Grundschule. z.B. 26 + 147 = 173. Sie starten mit der 6+7=13, so stellen Sie 3 in der Summe, und tragen, und so weiter - das heißt: Sie fügen zwei Ziffern und tragen Sie sich ein, wenn nötig.
Den code hat fast die gleiche Sache auf Binär-zahlen, aber mit einem kleinen kniff. Statt einer Stelle in einer Zeit, die es braucht, alle in einem gehen. Statt das tragen von position i-1 in i (D. H. einschließlich 1, wenn das hinzufügen von 2 und 4), den code hinzufügen, alle Karies in einer zweiten iteration. Also was es tut ist:
026+147 = 163 + 010 = 173 + 000
Für die binäre zahlen a=6=00110 und b=7=00111 erhalten Sie
Ersten finden Sie die trägt; das ist alles Positionen, in denen beide
a
undb
hat seine bit-set:int carry = (a & b) ;
Dann id noch der Zusatz von Ziffern, ignorieren Sie die tragen, und speichert es in
a
:a = a ^ b;
Diese reagieren auf6+7=3
im Beispiel.Den letzten Teil verschiebt sich das tragen auf die nächste Stelle, also die Gewährleistung der 1-carry-in dem Beispiel ist "umgezogen" von der 1 auf die 10:
carry << 1;
Die while-Schleife wird so lange fortgesetzt, wie es sich trägt, nicht enthalten in der Summe.
Den Variablen
b
undcarry
verwendet werden, für die "Durchführung" extra Ziffern. Zum Beispiel in der Binärdatei1+1 = 10
, aber10
ist eine zweistellige Zahl. Die1
im10
gelegt werden muss, in die nächste Ziffer der linken Seite. Das ist es, was diewhile()
Schleife in Ihrem Programm. Überall dort, wo1
Ziffern an der gleichen Stelle (a & b
),carry
ist auf das XOR vonb
(a ^ b
). dies gibt jeder Ziffer den Wert1
nur, wenn entwedera
oderb
, aber nicht beide, hat den Wert 2. (Wenn dabei die binäre Arithmetik, das ist genau das, was passiert;1+1 = 10
, also seit zwei1
s werden addiert, die Stelle ist0
). Danachcarry << 1
(carry*2
odercarry
verschoben Links von einem) zugeordnet istb
. Die Schleife wiederholt sich dann, unter Verwendung der neuen Werte vona
undb
bisb
null ist (was bedeutet, dasscarry
auch null).Jeden Fall denken alle zahlen in hier im binären system.
Was würden Sie in der Regel gerne, um herauszufinden, in solcher code ist ein "loop-invariant". In diesem Fall würde Man gerne sehen, dass a + b konstant ist, nach jeder iteration. So, wenn b zu 0 und wir verlassen die Schleife, ein muss, entspricht der Summe der ursprünglichen a-und b -. Der nächste Schritt ist, um sicherzustellen, dass die Schleife irgendwann beendet. Wir kommen später noch darauf zurück, lassen Sie uns zunächst herausfinden, unveränderlichen Teil, der in diesem Fall ist mit der Gleichberechtigung:
wo in der Schleife eine neue wird gleich alten a ^ b und b 2 * (a & b), das ist das gleiche wie (a & b) << 1. Das ist die Essenz von Deinem problem, herauszufinden, diese Gleichheit. Es ist genau, wie Sie das neben.
Zeige ich zwei Lösungen.
In beiden verwende ich eine einfache Tatsache, dass:
Wann immer x und y haben keinen gemeinsamen bits festgelegt.
Den kurzen Weg, um zu sehen, das formal ist zu beachten, dass:
Die langwierige Lösung basiert auf mathematischen Induktion folgt (dies könnte betrachtet werden ein übermaß von einigen, aber in meine option ist es Wert, es zu wissen):
Zunächst sicherstellen, dass es funktioniert mit a und b beide gleich null sind (Sie könnten auch versuchen, für eine bit-zahlen, die eine Menge erklären, wie dieser Algorithmus funktioniert). Nie vergessen Sie diesen Schritt, wenn mit Hilfe der mathematischen Induktion.
Nächsten, anzunehmen, diese Werke für die n-1-bit-zahlen, die wir bekommen haben, zu zeigen, dass es funktioniert für n bisschen zu. Jetzt schreiben a = 2a' + a" = 2a' ^ a 'und b = 2b' + b '= 2b' ^ b", wo a", b" sind in der Menge {0, 1} (dann ist 2a "und" haben keine gemeinsamen bits gesetzt!).
Dann:
Nun die Letzte Sache zu prüfen, ist, dass diese Schleife wirklich beendet.
um dies zu sehen, verwenden Sie die Tatsache, dass bei jedem Schritt a und b beide nicht negativ sind, und dass dies gilt nach jeder iteration.
Deshalb haben wir, die b <= a + b.
Weiter beachten Sie, dass nach n Schritten b hat zu enden, mit n Nullen. Daher können wir nicht mehr tun, als log_2(a+b) Schritte, da würden wir bekommen entweder b = 0 oder b = k * 2*n >= 2*n > 2**log_2(a+b) = a+b, widersprechende Annahme.
Hier ** bedeutet Potenzierung natürlich.
In Java-dieser Algorithmus funktioniert auch auf den negativen ganzen zahlen. Dieses ist, weil, wie negative Ganzzahlen gespeichert sind, in Java und in den meisten Programmiersprachen
Hier die addition und Subtraktion von signed-und unsigned-zahlen funktioniert genauso wie auf bits, also code, der funktioniert für zahlen ohne Vorzeichen werden auch für unterschrieben.
Er beruht auf der Tatsache, dass 1+1=10 (bit-Weise), d.h. "wenn ein Zusatz impliziert eine carry-bit, dann die Summe der aktuellen ist-stellige Spalte muss null sein". Denken Sie an die "<<" Betreiber der als "carry-bits nach Links", statt zu denken "Multiplikation eines int mit 2"
Hier ist eine nüchterne Beschreibung des Codes.
Ja, wie viele Antworten hier, es funktioniert wie rudimentär Schule Mathematik für das hinzufügen von zwei zahlen. Aber in Binärer Art und Weise.
Viel besser zu verstehen, mit Beispielen, kleinere Beispiele.