Warum ist abs(0x80000000) == 0x80000000?
Habe ich nur angefangen zu Lesen Hacker ' s Delight und definiert abs(-231), da -231. Warum ist das so?
Versuchte ich printf("%x", abs(0x80000000))
auf ein paar verschiedenen Systemen und ich wieder 0x80000000 auf alle von Ihnen.
- +1 für Lesen Hacker ' s Delight
- Danke! Kaum habe ich fertig Kapitel 1.
- Wenn Sie fertig sind der Lektüre des Buches schauen Sie sich die website für mehr gute Sachen in die gleiche Richtung: hackersdelight.org
Du musst angemeldet sein, um einen Kommentar abzugeben.
Für eine 32-bit-Datentyp, es ist kein Ausdruck von +2^31, weil die größte Zahl ist 2^31-1 ... Lesen Sie mehr über die Zweierkomplement ...
Tatsächlich, in C ist das Verhalten undefiniert. Ab dem C99-standard, §7.20.6.1/2:
und seine Fußnote:
Weil Ganzzahlen im Speicher gespeichert werden als Zweierkomplement-Binärzahl, die positive version der minimale Wert überläufe zurück ins negative.
Ist zu sagen, (in .NET, aber immer noch gilt):
Und
Offensichtlich, mathematisch |-231| 231. Wenn wir 32 bit für Ganzzahlen, stellen wir bei den meisten 232 zahlen. Wenn wir wollen, eine Darstellung, die symmetrisch um 0 ist, haben wir ein paar Entscheidungen zu treffen.
Für die folgenden, wie in Ihrer Frage, ich gehe davon aus, dass 32-bit-breiten zahlen. Mindestens ein bit-Muster verwendet werden muss, für 0. So, dass lässt uns mit 232-1 oder weniger bit-Muster für den rest der zahlen. Diese Zahl ist ungerade, so können wir entweder eine Vertretung, das ist nicht genau symmetrisch um null, oder eine Zahl dargestellt werden, mit zwei verschiedenen Darstellungen.
0x80000000
ist "negative null" (d.h., null), und0x00000000
ist "positive null" oder regelmäßige. null. In diesem Schema werden die meisten positiven Zahl0x7fffffff
(2147483647) und die negative Zahl ist0xffffffff
(-2147483647). Dieses Schema hat den Vorteil, dass es einfach für uns zu "entschlüsseln", und dass es symmetrisch ist. Dieses Schema hat den Nachteil, dass die Berechnunga + b
wenna
undb
unterschiedliche Zeichen ist ein Sonderfall und muss behandelt werden speziell.0x7fffffff
(2147483647), und die maximale negative Zahl ist0x80000000
(-2147483647). Es gibt zwei Repräsentationen der 0: positiv null ist0x00000000
und negativ null ist0xffffffff
. Diese Regelung hat auch Probleme mit Berechnungen mit negativen zahlen.1
zu. In diesem Schema gibt es nur eine 0, nämlich0x00000000
. Die positive Zahl ist0x7fffffff
(2147483647) und die negative Zahl ist0x80000000
(-2147483648). Es ist eine Asymmetrie in dieser Darstellung. Der Vorteil dieses Systems ist, dass man nicht zu tun haben mit besonderen Fällen für negative Zahl ist. Die Vertretung übernimmt von Ihnen die richtige Antwort, solange das Ergebnis nicht überlauf -. Aus diesem Grund, die meisten der aktuellen hardware Ganzzahlen entspricht in dieser Darstellung.In Zweierkomplement-Darstellung, es gibt keine Möglichkeit zu vertreten, 231. In der Tat, wenn Sie sich Ihre compiler
limits.h
oder gleichwertig-Datei, sehen Sie möglicherweise eine definition fürINT_MIN
so:Dies getan, anstatt
weil 2147483648 ist zu groß, um in einem
int
in einer 32-bit-Zweierkomplement-Darstellung. Durch die Zeit, die der unäre minus-operator "wird" die Zahl, mit zu arbeiten, es ist zu spät: überlauf hat bereits stattgefunden, und Sie kann es nicht reparieren.So, zur Beantwortung Ihrer ursprünglichen Frage, der absolute Wert der negativen Zahl in Zweierkomplement-Darstellung dargestellt werden können, dass die Kodierung. Auch, von oben, von einem negativen Wert auf einen positiven Wert im Zweierkomplement-Darstellung, Sie nehmen Ihre eigenen ergänzen und addieren dann 1. So, für
0x80000000
:erhalten Sie die ursprüngliche Zahl zurück.
Dies geht zurück auf, wie zahlen gespeichert werden.
Negative zahlen gespeichert, Zweierkomplement. Der Algorithmus geht wie ...
Spiegeln alle bits, dann fügen Sie 1.
Anhand von acht bit-zahlen für die Beispiele ...
+0 = -0
00000000 -> 11111111, 11111111 + 1 = 100000000
(aber aufgrund der Einschränkung von bits, dies wird 00000000).
UND...
-128 [aka -(2^7)] ist gleich -(-128)
10000000 -> 01111111, 01111111 + 1 = 10000000
Hoffe, das hilft.
Die Darstellung einer zweier-Komplement-Zahl hat das höchstwertige bit als negative Zahl. 0x80000000 ist 1, gefolgt von 31 Nullen, die erste 1 steht für -2^31 2^31. Daher gibt es keine Möglichkeit zu vertreten, 2^31, die als die größte positive Zahl ist 0x7FFFFFFF, die 0, gefolgt von 31, das entspricht 2^31-1.
abs(0x80000000) ist daher undefiniert in der Zweierkomplement, da es zu groß ist, da dies die Maschine nur gibt und gibt Ihnen 0x80000000 wieder. In der Regel zumindest.
Ich denke, die Art und Weise
abs
funktioniert, ist, überprüfen Sie zuerst diesign bit
von der Anzahl. Wenn seine klare nichts tun, als die Nummer bereits+ve
else return die2's complement
von der Anzahl. In Ihrem Fall wird die Zahl-ve
und wir müssen zu finden sein2's complement
. Aber die 2 ergänzen von0x80000000
passiert0x80000000
selbst.0x8000.. gespeichert ist, als 10000.... (Binär). Dies ist bekannt als zweit ergänzen, was bedeutet, dass das höchste bit (der Links) wird zum speichern der Zeichen von Wert und negative Werte gespeichert werden, mit negativen Binär - 1. Die abs () - Funktion überprüft nun die signbit, sieht, dass es eingestellt ist, und berechnet den positiven Wert.
negiert, dass alle bits in der variable
was in 01111...
die Ergebnisse wieder in die 1000...
0x8000... wir begannen mit
Nun, dies ist eine negative Zahl wieder, die wir nicht wollen, der Grund ist ein überlauf, versuchen Sie, die Anzahl 0x9000... das ist 10010...
hinzufügen eines Ergebnisse in 01110...
Mit dieser Nummer ist der überlauf gestoppt, indem das bit 0 auf der rechten
weil es nutzt die neg-Anweisung zum ausführen dieses Vorgangs.
In der Kunst der Assembler-Programmierung Buch, das Sie so gesagt.
Quelle :http://www.arl.wustl.edu/~lockwood/Klasse/cs306/Bücher/artofasm/Chapter_6/CH06-2.html#HEADING2-313
So wird es gesetzt, das overflow-flag und werden still.Das ist der Grund.