Hallo alle zusammen,
bei Aufgaben (Einführung in die Programmierung) in denen ich prüfen
soll, ob eine Zahl im Wertebereich liegt, und wie die Zahl dann
dargestellt wird falls nicht, tue ich mich irgendwie schwer.
Bspw. habe ich die Zahl 384 von der ich weiß, wenn ich sie in byte
konvertiere sie als -128 dargestellt wird.
byte läuft ja von -128 bis 127.
Irgendwie verstehe ich nicht, warum sie als -128 dargestellt wird. Also
klar, ich weiß das der ab 127 bei -128 weiter läuft... Aber:
Ich würde es z. B. so machen.
127 + 128 + 127 = 2 und ich wäre bei -128 angekommen (oder nicht?).
Dann müsste doch die Darstellung -126 sein und nicht -128 sein.
Klar - sollte sie nicht. -128 ist schon richtig, aber wie kann ich
soetwas denn wirklich "bullet proof" per Hand rechnen so das ich mich da
nicht andauernd um minimal-Werte verhauhe?
Liebe Grüße
Erstmal Vielen Dank für die Antworten.
Wir rechnen auf Grundlage von Java. Ich glaube Java stellt alle Zahlen
im Zweierkomplement dar.
Rufus Τ. Firefly schrieb:> Kukuku schrieb:>> byte läuft ja von -128 bis 127.>> Tut es das?
Das steht so zumindest in meinem Script.
von -2^7 bis -2^7 - 1
Dummschwaetzer schrieb:> 384: 0x180> aber: nur 8Bit! : 0x80;> damit hast du -128;
Auch wenn sich das gut anhört habe ich das lieder nicht verstanden.^^
Liebe Grüße und danke schonmal für die tolle Hilfe.
Also vielleicht ist nicht ganz klar was ich möchte.
ich habe soetwas gegeben:
(byte) 0x180
und ich soll jetzt sagen, welcher Wert nach der Konvertierung
herauskommt. Ich kann das leider nur nicht rechnen, weil ich mich immer
um wenige Stellen vertue. Ich würde nämlich die 180 per Hornerschema
Dezimal darstellen und dann bis "0" loslaufen und gucken wie oft meine
Dezimalzahl in -128 bis 127 passt und dann gucken wo ich herauskomme.
Aber bei mir kommt dann immer -126 heraus, dabei sagt auch meine Ausgabe
in Java das es -128 sein soll.
Wie kann ich das schnell und einfach per Hand anstellen?
Ich kenne mich leider kaum in Java aus, aber die Darstellung der
negativen, ganzen Zahlen mittels Zweierkomplement ist einfach
alogithmisch durchführbar. Hier mal ein paar Anmerkungen in Kürze:
1) Du musst erstmal wissen ob die Zahl als negative Zahl betrachtet
werden soll, denn im Speicher sind nur 0 und 1.
2) Umrechnen der Zahl in Binär:
1 1000 0000
3) Invertieren (= Einerkomplement):
0 0111 1111
4) Addieren von 1 (= Zweierkomplement):
0 1000 0000
5) Zurück ins Dezimal:
128
6) Da du weißt, dass es sich um eine negative Zahl handelt:
-128
Bei Wikipedia ist das recht gut beschrieben.
Gruß
Dennis
P.S.: Den Bezug zum Horner-Schema verstehe ich nicht...!?
Noch eine Ergänzung:
Unter [1] ist der von dir angegebene Wertebereich auch noch mal
angegeben. Somit sollte der Aufgabentyp keine Probleme mehr bereiten!
:-)
Gruß Dennis
[1] http://www.factsandmore.ch/?p=478
Dennis S. schrieb:> 1) Du musst erstmal wissen ob die Zahl als negative Zahl betrachtet> werden soll, denn im Speicher sind nur 0 und 1.> 2) Umrechnen der Zahl in Binär:> 1 1000 0000> 3) Invertieren (= Einerkomplement):> 0 0111 1111> 4) Addieren von 1 (= Zweierkomplement):> 0 1000 0000> 5) Zurück ins Dezimal:> 128> 6) Da du weißt, dass es sich um eine negative Zahl handelt:> -128
Hallo Dennis. Angenommen deine Rechnung würde stimmen, wäre Schritt 5
und 6 etwas sehr geschustert. Das da jetzt 128 rauskommt und das in den
Wertebereich von byte passt, ist nur Zufall. Und eine weitere Überlegung
zur negativen Zahl müsste ich dann trotzdem anstellen.
Du wandelst falsch ins Einerkomplement um.
Das Einerkomplement von 110000000 (= 384) ist 0110000000 (also einfach
vorne eine 0 dran hängen). Das was du in Schritt 2 darstellt ist das
Einerkomplement von 127.
Das zweierkomplement von 0110000000 ist dann 1010000000 (einfach von
rechts bis zur ersten 1, dann invertieren - so kann man schritt 2 und 3
zusammen packen) und daraus kann ich überhaupt keine Schlüsse über den
Wert der Zahl ziehen, nur das ich zur Darstellung im Zweierkomplement
von 384 eben 9 bit brauche, ich aber bei byte nur ausgeschrieben 7 bit
zur Verfügung habe. => folgt nur das die Zahl nicht in meinen
Wertebereich passt, aber bei Java gibts eben Over- und Underflow.
Also so kommen wir offensichtlich nicht weiter.
Dennis S. schrieb:> P.S.: Den Bezug zum Horner-Schema verstehe ich nicht...!?
Naja. Ich kann jede Zahl mittels Horner Schema in einer Zahl beliebeiger
Basis umwandeln.
0x180
Mittels Horner Schema Dezimal dargestellt.
180
0 + 1 = 1
1 * 16 = 16
16 + 8 = 24
24 * 16 = 384
384 + 0 = 384
Kukuku schrieb:> Also vielleicht ist nicht ganz klar was ich möchte.>> ich habe soetwas gegeben:>> (byte) 0x180
Die 0x180 sind 3 Hexadezimale Nibble, oder anders ausgedrückt 12 Bit.
Ein Byte hat aber nicht 12 Bit (3 Nibbles) sondern dessen nur 8 (2
Nibbles).
D.h. da muss irgendwas unter den Tisch fallen.
Das Problem ist ungefähr dasselbe, wie wenn du ein Formular hast, in
welches du eine 2-stellige Zahl eintragen sollst, du aber eine
3-stellige Zahl hast.
1
+---+---+
2
Aufgabe: schreibe die Zahl 378 in die Felder | | |
3
+---+---+
Es geht nicht. Iregendwas muss unter den Tisch fallen. Du kannst
1
+---+---+
2
| 7 | 8 |
3
+---+---+
reinschreiben, aber das wars dann auch schon (ok, du hättest auch 37
reinschreiben können, aber das ist nicht das was auf einem Computer
passiert).
Dazu musst du überhaupt nichts rechnen, sondern dir nur die Ausgangszahl
ansehen und wohin sie konvertiert wird.
In deinem Fall versuchst du die Hex-Zahl 0x180 in einem Byte
1
+---+---+
2
| | |
3
+---+---+
unterzubringen, was natürlich nicht geht, weil 1 Byte nur maximal
2-stellige Hex-Zahlen aufnehmen kann.
1
+---+---+
2
| 8 | 0 |
3
+---+---+
Man kann das natürlich auch binär betrachten. Die Hex-Zahl 0x180 wäre
binär
1
1 1000 0000
ein Byte hat aber keine 9 Bit. 1 Byte hat 8 Bit. Also muss wieder etwas
unter den Tisch fallen. Wie üblich sind es die höchstwertigeren Stellen,
die da wegfallen
1
1 1000 0000
2
|
3
| Reduktion auf 8 Bit
4
v
5
1000 0000
und wieder landen wir bei den 0x80, die denn entweder als signed oder
als unsigned Zahl ausgegeben werden können. Als signed Zahl ausgegeben
wäre das (wegen 2-er Komplement) -128. Als unsigned Zahl wäre das ganz
banal +128.
Das du die dezimalen 380 natürlich erst mal fehlerfrei in eine Hex-Zahl
umwandeln können musst, ist eine andere Sache. Tip: Der
Windows-Taschenrechner in der Einstellung "Programmierer" kann dir
helfen, deine Umrechnungen zu kontrollieren.
Kukuku schrieb:> Hallo Dennis. Angenommen deine Rechnung würde stimmen, wäre Schritt 5> und 6 etwas sehr geschustert. Das da jetzt 128 rauskommt und das in den> Wertebereich von byte passt, ist nur Zufall. Und eine weitere Überlegung> zur negativen Zahl müsste ich dann trotzdem anstellen.
Was heißt denn "geschustert"? Wie gesagt, das sind Notizen. Das Thema
wird ja auf unzähligen Webseiten ausgekaut, weswegen ich hier nicht
erkläre wie man Zahlensysteme umrechnet.
> Du wandelst falsch ins Einerkomplement um.> Das Einerkomplement von 110000000 (= 384) ist 0110000000 (also einfach> vorne eine 0 dran hängen). Das was du in Schritt 2 darstellt ist das> Einerkomplement von 127.
Bist du dir da sicher? Einerkomplement wird durch invertieren der Bits
gebildet. Siehe z.B.: https://de.wikipedia.org/wiki/Einerkomplement> Naja. Ich kann jede Zahl mittels Horner Schema in einer Zahl beliebeiger> Basis umwandeln.
Sieht umständlich aus. Mag aber daran liegen, dass ich das Horner-Schema
nie in dem Zusammenhang genutzt habe.
Gruß Dennis
Edit: Karl Heinz ist wie immer der Schnellste! ;-)
Dennis schrieb
> Bist du dir da sicher?
Meine Erklärung ist falsch, sorry, aber deine Rechnung ist trotzdem
falsch^^ Das mit der 0 dran hängen ist direkt die Umwandlung ins
Zweierkomplement (funktioniert nur bei positiven Zahlen).
z. B. 5 ist Binär 101
5 im Zweierkomplement ist dann vorne die 0 dran hängen = 0101.
Aber damit kann man dann auch direkt die -5 im zweier Komplement
herleiten
1) 5 Binär = 101
2) 5 im Zweierkomplement 0101 (0 vorne dran hängen).
3) von 5 zu -5, man nehme 0101, bis zur ersten 1 von rechts, rest
invertieren = 1011
Also das was du in Schritt 2 darstellst, ist das Zweierkomplement von
127, bzw wenn du die 0en vorne komplett streichst einfach nur 127 binär.
Kukuku schrieb:> Dennis schrieb>> Bist du dir da sicher?>> Meine Erklärung ist falsch, sorry, aber deine Rechnung ist trotzdem> falsch^^ Das mit der 0 dran hängen ist direkt die Umwandlung ins> Zweierkomplement (funktioniert nur bei positiven Zahlen).
Nö.
Das ist Quatsch.
Einerkomplement bzw. Zweierkomplement hat per se erst mal nichts mit
Bitzahlen zu tun.
Dass da eine führende 0 vorgestellt wird hat einfach nur damit zu tun,
dass du bei Überlauf eine Stelle mehr brauchen würdest. Das ist aber im
Grunde recht uninteressant, weil die überlaufenden Bits sowieso nicht
mehr berücksichtigt werden.
Einerkomplement: alle Bits umdrehen
Zweierkomplement: alle Bits umdrehen UND dann noch 1 addieren.
> z. B. 5 ist Binär 101>> 5 im Zweierkomplement ist dann vorne die 0 dran hängen = 0101.>>> Aber damit kann man dann auch direkt die -5 im zweier Komplement> herleiten>>> 1) 5 Binär = 101> 2) 5 im Zweierkomplement 0101 (0 vorne dran hängen).> 3) von 5 zu -5, man nehme 0101, bis zur ersten 1 von rechts, rest> invertieren = 1011
wie kann 1011 in einem System mit 3 Bits ein gültiges Ergebnis sein?
Entweder deine 5 hatte schon immer 4 Bits 0101 oder du rechnest eben
alles mit 3 Bits.
Das sind führende 0-en! Davon kannst du links so viele anhängen wie du
willst, deswegen ändert sich die Zahl nicht. Sinnvollerweise wird man
soviele führende 0-en anhängen, wie man in der gewählten Repräsentierung
(zb 1 Byte == 8 Bit) benötigt. Aber wenn du willst kannst du auch 379
führende 0-en anhängen. Die 5 bleibt nach wie vor eine 5. Und hat mit
einem Einerkomplement nicht das geringste zu tun.
Karl Heinz schrieb:>> 1) 5 Binär = 101>> 2) 5 im Zweierkomplement 0101 (0 vorne dran hängen).>> 3) von 5 zu -5, man nehme 0101, bis zur ersten 1 von rechts, rest>> invertieren = 1011
Da scheint mir ein Missverständnis vorzuliegen.
2-er Komplement bezeichnet das Vorgehen, welches man benutzt um aus
einer Zahl die jeweils negative Zahl zu machen.
Der Vorgang um aus
1
+5 0000 0101
2
3
1111 1010 alle Bits umdrehen
4
1111 1011 noch 1 addieren
5
6
1111 1011 ist das 8-Bit Bitmuster für -5
zu erhalten, den nennt man das 2-er Komplement.
gegenprobe: das negative von -5 ist ja +5
1
-5 1111 1011
2
3
0000 0100 alle Bits umdrehen
4
0000 0101 noch 1 addieren
5
6
das Bitmuster 0000 0101 ist das 8-Biot Bitmuster für +5
passt.
Noch eine Probe.
Es muss ja gelten -5 + 5 ergibt 0
1
1111 1011 -5
2
+ 0000 0101 +5
3
--------------
4
1 0000 0000
5
6
da wir aber in 8 Bit rechnen, ist der Überlauf in die
7
9. Stelle uninteressant, das Bit fällt einfach weg
Karl Heinz schrieb:> Es muss ja gelten -5 + 5 ergibt 0> ...> passt.
(und nebenbei bemerkt ist genau das letzte Beispiel schon die halbe
Miete um die Bedeutung des 2-er Komplements zu verstehen. Ich muss mich
nicht darum kümmern ob Zahlen positiv oder negativ sind. Ich addiere die
einfach und es kommt immer das richtige raus - nur bei einem
Overflow/Underflow muss man aufpassen ob der real ist, oder ob er durch
die Art der Darstellung hervorgerufen wurde)
um +8 + (-6) zu rechnen:
1
+8 0000 1000
um die Bitrepräsentierung für -6 zu bestimmen, nehm ich erst mal die
Bitdarstellung für +6
1
+6 0000 0110
und wende das 2-er komplement an, um das zu negieren
1
0000 0110
2
3
1111 1001 alle Bits umdrehen
4
1111 1010 und noch 1 addieren
die Binärdastellung für -6 lautet also 1111 1010
jetzt kann man die Addition machen
1
+8 0000 1000
2
-6 + 1111 1010
3
------------
4
1 0000 0010
wieder: Da wir uns im 8 Bit Raum gewegen, fällt das Übertragsbit an der
9. Stelle weg, und das Ergebnis lautet
1
0000 0010 = 2
und 2 ist ja offensichtlich korrekt für 8 + (-6)
Aber lass uns mal 6 - 8 rechnen.
Das bitmuster für +6 lautet
1
+6 0000 0110
das Bitmuster für -8 lautet?
Na das bestimmen wir wieder aus dem Muster für +8, in dem wir die +8
negieren.
1
+8 0000 1000
2
3
1111 0111 alle Bits umdrehen
4
1111 1000 und noch 1 addieren
Damit sind alle Zutaten beisammen um 6 + (-8) rechnen zu können
1
+6 0000 0110
2
-8 + 1111 1000
3
------------
4
1111 1110
da das Ergebnis hier in der höchsten gültigen Stelle
1
1111 1110
2
^
ein 1 Bit ist, wissen wir, dass es sich um ein negatives Ergebnis
handelt. Aber welches?
nun dazu negieren wir einfach das Ergebnis, wir machen also aus -x ein
+x und sehen uns an was dieses x ist. EIne Zahl negieren ist aber
leicht. genau das ist ja, was das 2-er Komplement macht. ALso
1
Zahl 1111 1110
2
3
0000 0001 alle Bits umdrehen
4
0000 0010 und noch 1 addieren
Das Ergebnis, 0000 0010, erkenn wir als die Binärrepräsentierung von
dezimal 2 wieder. Wenn das aber +2 ist, dann muss die Ausgangsbasis 1111
1110 ein -2 gewesen sein.
6 + (-8) liefert also das Ergebnis -2.
Und auch das ist offensichtlich korrekt.
@Kukuku
Auch mit einem Hammer bekommst Du 384 in kein Byte.
Ein einfaches Beispiel hierzu: 8 Stellen (binär) 0 ... 255
2 Stellen (dezimal) 0 ... 99
Alle Zahlen oberhalb von 255 (bin) oder 99 (dez) klemmen.
Die ganze Spielerei mit dem Vorzeichen bringt auch nichts, denn 8
Stellen sind 8 Stellen.
Willst Du ein Vorzeichen haben, so klaust Du Dir eine Stelle und hast
nur noch 7 Stellen. Die 8. Stelle ist dann das Vorzeichen. Für die
Zahlen bleiben dann nur noch 7 Bit also 127 bis 0 bis -128. Oder so.
Nur mal zur Vervollständigung des Durcheinanders:
Führende Nullen werden vorangestellt und nicht angehängt. Durch Anhängen
einer Null wird eine Zahl um 1 Ziffernstelle nach links geschoben, also
mit der Systemzahl multipliziert. Dezimalzahlen haben keine führenden
Nullen, außer im Display von alten Rechenmaschinen, wo zum Rechnen noch
an einer Kurbel gedreht werden muß.
Noch kurz der Verweis auf die Java-Dokumentation.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html
"A narrowing conversion of a signed integer to an integral type T simply
discards all but the n lowest order bits, where n is the number of bits
used to represent type T. In addition to a possible loss of information
about the magnitude of the numeric value, this may cause the sign of the
resulting value to differ from the sign of the input value. "