Frage zum Zweierkomplement



  • Ey gude!

    Ich schaue mir gerade die Bildung des Zweierkomplements von negativen Zahlen an. Ich weiß, dass es nun nur noch eine Darstellung für 0 gibt und die Addition zweier Binärzahlen gut funktioniert.

    Ich verstehe jedoch nicht, WARUM ich das Zweierkomplement berechne, wie ich es berechne. Wenn meine Dezimalzahl negativ ist, dann setze ich das msb erst mal auf 1. Nun errechne ich die binäre Zahl von\begin{math} 2^{N-1} + k \end{math}, wobei k meine negative Dezimalzahl und N die Anzahl der verfügbaren Bits ist.

    Warum mache ich das so? Was ist daran so toll und WARUM geht die Addition nicht schief?

    Mir ist einfach nicht klar, was ich da mache...

    Danke euch 🙂

    PS.: Warum geht mein Latex nicht 😕



  • Nehmen wir das Zehnerkomeplent.
    Du hast Doc Abi. In den veraltetetn Tabellenwerken stand immer 0.2683 und so.
    Du mußtest oft die Gegenwahrscheinlichkeit 1-0.2683 ausrechnen und hast es getippt, WEIL DU NOCH KEIN HACKER WARST!

    1.0000
    - 0.2683
    = ?
    

    Das weiß ja kein Mensch.
    Aber

    0.9999
    - 0.2683
    = ?
    

    Ach, das ist Trivial, wenn man's man gesehen hat.

    0.9999
    - 0.2683
    = 0.7316
    

    Einfach jede Ziffer auf 9 ergänzen. Das ist ein Wichtiger Trick. Es kann kein Überlauf entstehen. Es klappt immer!

    Also nachmal:

    0.9999
    - 0.2683
    = 0.7316
    

    Und jetzt die Hauptaufgabe:

    1.0000
    - 0.2683
    = 0.7317 (einfach nur 0.0001 dazurechnen, also normalwerweise nur die letze Stelle um 1 erhöhen!).
    

    Übungsaufgabe:
    Was ist
    10-pi, also

    10.00000000
    -  3.14159265
    

    ?

    Wenn Du das verinnerlichst, ist es eigentlich schon durch.
    (Hoffe ich.)



  • freakC++ schrieb:

    Warum mache ich das so? Was ist daran so toll und WARUM geht die Addition nicht schief?

    Weil das Zehnerkomlemenet ja gerde (nehmen wir mal 4-stellige Zahlen an)

    10000
    -6479
    =3521 (beachte die +1 am Ende)
    ist.
    Also immer wenn ich eine Zahl -6479 rechnen will, kann ich stattdessen auch +3521 rechnen.

    Test:
      8234
    - 6479
    = 1755
    
    Aber
      8234
    + 3521
    =11755
    
    Also
      8234
    + 3521
    = 1755
    

    Die Überlaufziffer wird ja weggeworfen.

    Also es ist egal, ob ich A-B rechne oder A+(10000-B), weil die Überlaufziffer weggeworfen wird.
    Dann können wir definieren(!), daß -B gleich (10000-B) ist. Und wir spraren uns, die Transistoren für ein Subtrahierwerk.
    Durch diese schlaue Zahlendefinition können wir allein mit einem Addierwerk auskommen und sparen die Hälfte der Transistoren.



  • Fahrradtacho:
    3 stellig, 900 km schon gefahren. Was passiert, wenn wir noch 600 km weiterfahren?

    Wieviel wären 600 + 400? (oder gar 900 - 400)

    oder besser: wieviel ist 7777 - 896, wenn man es im Kopf ausrechnet?



  • joa...das macht Sinn 🙂 Zur Übung habe ich einfach mal eine Aufgabe gerechnet. Die folgenden zwei Komplementzahlen wollte ich addieren:

    00101010 + 10000000

    Das Ergebnis lautet nach meiner Rechnung: 10101010

    Jetzt habe ich das im Dezimalsystem überprüft.

    00101010 = 42
    10000000 = -256

    42 + (-256) = -214

    Das Ergebnis ist bei mir aber falsch, denn 10101010 ist nicht -214, sondern -42, wenn ich das Ergebnis nach dem Algorithmus in eine Dezimalzahl umwandle.

    Was mache ich falsch?

    Vielen Dank
    lg, freakC++



  • Das wimmelt ja von Fehlern.

    freakC++ schrieb:

    joa...das macht Sinn 🙂 Zur Übung habe ich einfach mal eine Aufgabe gerechnet. Die folgenden zwei Komplementzahlen wollte ich addieren:

    00101010 + 10000000

    Also +42 + -128 = -86

    freakC++ schrieb:

    Das Ergebnis lautet nach meiner Rechnung: 10101010

    Ist doch supi.

    Jetzt habe ich das im Dezimalsystem überprüft.
    00101010 = 42
    10000000 = -256
    42 + (-256) = -214

    Der Behauptung "10000000 = -256" kann ich nicht folgen.

    freakC++ schrieb:

    Das Ergebnis ist bei mir aber falsch, denn 10101010 ist nicht -214, sondern -42, wenn ich das Ergebnis nach dem Algorithmus in eine Dezimalzahl umwandle.

    Wo haste denn jetzt die -42 her?

    11111111
    - 10101010
    = 01010101
    + 00000001
    = 01010110
    = 86(zur Basis 10)



  • Ach verdammt. Das ist ja -128 und nicht -256. Na klar. Dann macht alles Sinn. Mir ist aber noch ein anderes Problem über den Weg gelaufen, das ich gerade nicht so banal lösen kann (obwohl es das wahrscheinlich ist).

    Ich addiere wieder zwei Zweierkomplementzahlen:

    01000011 + 01000100 = 10000111

    Ohen es dezimal umzurechnen, sehe ich, dass da ja was nicht stimmen kann. Ich addiere zwei positive Zahlen (beide Summanden fangen mit 0 an) und es kommt etwas Negatives heraus, denn das Ergebnis fängt mit 1 an. Wie kann das denn sein?

    Danke und lg
    freakC++



  • freakC++ schrieb:

    Ach verdammt. Das ist ja -128 und nicht -256. Na klar. Dann macht alles Sinn. Mir ist aber noch ein anderes Problem über den Weg gelaufen, das ich gerade nicht so banal lösen kann (obwohl es das wahrscheinlich ist).

    Ich addiere wieder zwei Zweierkomplementzahlen:

    01000011 + 01000100 = 10000111

    Ohen es dezimal umzurechnen, sehe ich, dass da ja was nicht stimmen kann. Ich addiere zwei positive Zahlen (beide Summanden fangen mit 0 an) und es kommt etwas Negatives heraus, denn das Ergebnis fängt mit 1 an. Wie kann das denn sein?

    Danke und lg
    freakC++

    Ganz normaler Überlauf.
    Ergebnis paßt nicht in die Registerbreite rein.
    In dem Fall bei 8 Bit passiert Folgendes, wenn ich immer +1 rechne:
    0 1 2 3 4 5 ... 125 126 127 -128 -127 -126 ... -4 -3 -2 -1
    Würdest Du Zu Deinem Minusergebnis noch 256 draufaddieren, wäre es wieder richtig.



  • Oder um es anderes zu formulieren: Beim Zweierkomplement rechnest du immer in Z/2^32Z. Der einzige Unterschied zwischen unsigned und signed ist die Wahl des Repräsentanten. Das hat den Vorteil, dass man bei den meisten Grundrechenoperationen gar nicht zwischen signed und unsigned unterscheiden muss.



  • Hallo zusammen,

    stimmt, ein Überlauf. Daran hatte ich gar nicht mehr gedacht. Soweit ich mich entsinnen kann, darf man diesen im Zweierkomplement getrost ignorieren. Leider komme ich so immer noch auf das falscher Ergebnis. Ich habe so gerechnet:

    Die Aufgabe lautete: 01000011 + 01000100 = 10000111

    Nun rechne ich jede Zahl ins Dezimalsystem um. Dazu invertiere ich erst alle Bits und addiere dann 1 dazu:

    01000011 --> 10111100 --> 10111101 = 189

    01000100 --> 10111011 --> 10111100 = 188

    10000111 --> 01111000 --> 01111001 = 121

    Leider ergibt 189 + 188 nicht 121. Was mache ich noch falsch?

    Danke euch 🙂
    lg, freakC++



  • ups



  • freakC++ schrieb:

    Hallo zusammen,

    stimmt, ein Überlauf. Daran hatte ich gar nicht mehr gedacht. Soweit ich mich entsinnen kann, darf man diesen im Zweierkomplement getrost ignorieren. Leider komme ich so immer noch auf das falscher Ergebnis. Ich habe so gerechnet:

    Die Aufgabe lautete: 01000011 + 01000100 = 10000111

    Ok.

    freakC++ schrieb:

    Nun rechne ich jede Zahl ins Dezimalsystem um. Dazu invertiere ich erst alle Bits und addiere dann 1 dazu:

    01000011 --> 10111100 --> 10111101 = 189

    01000100 --> 10111011 --> 10111100 = 188

    10000111 --> 01111000 --> 01111001 = 121

    Unfug. Mit "Dazu invertiere ich erst alle Bits und addiere dann 1 dazu" negierst Du die Zahlen.

    freakC++ schrieb:

    Leider ergibt 189 + 188 nicht 121. Was mache ich noch falsch?

    189 + 188 = 121 (modulo 256)
    Aber das hat nichts mit der Aufgabe zu tun.

    Die Aufgabe lautete: 01000011 + 01000100 = 10000111
    Also 67 + 68 = 135
    unsigned char würde man es als 135 lesen (ohne Überlaufproblem, weil das Ergebnis in den Bereich 0 bis 255 paßt)
    als signed char würde man es als 135-256=-121 lesen (mit Überlaufproblem, weil das Ergebis nicht in den Bereich -128 bis +127 paßt)

    Was Du gerechnet hast, was umnständlich und ginge im Prinzip so weiter:
    Die Aufgabe lautete: 67 + 68 =
    Ich negiere beide Zahlen
    Die Ersatzaufgabe lautete: -67 + -68 =
    rechnerechne
    Die Ersatzaufgabe lautete: -67 + -68 = -135
    Das Ersatzergebnis lautet -135
    Ich negiere das Ersatzergebnis
    Der Ergebnis lautet 135.

    Aber mit Zweierkomplemetdarstellung, also signed Typ, gibt es ja -135 nicht, sondern das wäre -135+256=-121

    Also
    Die Aufgabe lautete: 67 + 68 =
    Ich negiere beide Zahlen
    Die Ersatzaufgabe lautete: -67 + -68 =
    rechnerechne
    Die Ersatzaufgabe lautete: -67 + -68 = 121
    Das Ersatzergebnis lautet -121
    Ich negiere das Ersatzergebnis
    Der Ergebnis lautet -121. Und der Überlauf ist passiert, das echte Ergebnis wäre -121+256=135

    Wendest Du die Negierung auf unsigned an, interpretiert es sich nicht als 0-zahl, sondern als 256-zahl.
    Die Aufgabe lautete: 67 + 68 =
    01000011 --> 10111100 --> 10111101 = 189
    01000100 --> 10111011 --> 10111100 = 188
    Du hast daraus gemacht (256-67)+(256-68) = 189+188

    10000111 --> 01111000 --> 01111001 = 121
    Du hast daraus gemacht (256-67)+(256-68) = 377, paßt aber nicht, also 377-256=121, Überlauf halt

    Und jetzt das Ersatzergebnis noch korrigieren, also negieren, also Zweierkomplement ausführen.
    256-121=135.

    Voll übertrieben umständlich, erst beide Zahlen zu negieren und dann das Ergebnis auch.



  • ...



  • Amigos!! Der Wurm ist noch immer drin. Also ich habe noch eine Frage 🙂

    Ich habe es so verstanden, dass auch im Zweierkomplement die 0 eine positive Zahl kennzeichnet und eine 1 die negative. Ok. Außerdem habe ich gelernt, dass man Overflows ignorieren, also streichen kann.

    Nun ist das Ergebnis ja 10000111. Es ist ein Bit "zu groß". Als dachte ich mir: Mmh...ich darf das msb streichen, da es ja zu viel ist. Also würde die Zahl 0000111 herauskommen.

    Das ist wiederum Blödsinn. Das richtige Ergebnis kriege ich nur mit 10000111. Warum darf ich jetzt plötzlich nicht mehr den Overflow streichen?

    Ich addiere zwei Zweierkomplementzahlen. Kann es sein, dass das Ergebnis nicht mehr im Zweierkomplement ist?? Dann würde es auch Sinn machen, warum die Zahl mit 1 beginnt und trotzdem positiv ist 🙂

    Vielen Dank für eure Geduld 🤡
    lg, freakC++



  • 0100 0011
    4     3   ->d 4 * 16 + 3 = 67     //43h
    
    0100 0100 ->d 4 * 16 + 4 = 68  67 und 68 zusammenzählen: 120 + 15 = 135
    4     4                           //44h
    
    43h
    44h
    --
    87h     8*16 (128) + 7 -> 135
    
    ->1000 0111
    
    negativ und positiv:
    alle ab 80h negativ, weil ja 1000 0000 eine 1 vorne hat
    

    Wie wäre das, wenn man auf dem Fahrradtacho mit 3 Stellen (normalerweise haben die 4 Stellen) negative km ohne Minuszeichen darstellen wollte?

    Man kann wirklich durcheinander kommen bei dieser Frage. Hexadezimalzahlen oder Oktalzahlendarstellungen helfen enorm beim Überprüfen von Binärrechnungen.

    Mach dir deine Rechenbeispiele so einfach es geht, und so anschaulich wie möglich, sonst schreiben Volkard und ich uns hier noch die Finger wund 😉

    p.s.: 128 - 7 ( 80h + 7)?



  • Der Witz ist, daß Du gar nicht die Absicht hast, die natürlichen Zahlen als Zahlenraum zu haben, sondern nur den Restklassenring module 256.

    Die R17 stellt eine ganze Klasse von Zahlen dar, und zwar die 17, die 17+256, die 17+2256, die 17-257 und so weiter, in der Tat unendlich viele.
    Die R19 stellt entsprechend alle Zahlen der Form 19+z
    256 dar.

    Rechet man irgend eine Zahl aus R17 plus irgendeine Zahl aus R19, so landet man sicher bei einer Zahl aus R36.

    Rechnet man irghendeine Zahl aus R67 plus irgend eine Zahl aus R68, so landet man bei einer Zahl aus R135.

    Das ist wiederum Blödsinn. Das richtige Ergebnis kriege ich nur mit 10000111. Warum darf ich jetzt plötzlich nicht mehr den Overflow streichen?

    Den darfst Du streichen, wenn Du mit Restklassenringen rechnest und Dir dessen bewußt bist. Dann rechnest Du das, was der Computer auch rechnet, nämlich läßt Overflows fallen.

    Nun ist das Ergebnis ja 10000111. Es ist ein Bit "zu groß". Als dachte ich mir: Mmh...ich darf das msb streichen, da es ja zu viel ist. Also würde die Zahl 0000111 herauskommen.

    Doch nicht das MSB streichen. Das Streichen, was rausfällt, bei 8-Bit-Zahlen also das neunte Bit streichen.

    Du willst gerade das MSB streichen, das wäre nicht ok.

    Oder bist Du wieder in Zweierkomplementdarstellung, hast also auch negative Zahlen?
    Dann nennen wir die Restklassen zum Teil um:
    In R255 sind ja die Zahlen …-513,-257,-1,255,511…
    Ob ich den jetzt R255 oder R511 oder R-1 nenne, ist recht egal.

    R0 bleibt R0
    R1 bleibt R1
    usw
    R127 bleibt R127
    aber R255 wird zu R-1
    und R254 wird zu R-2
    usw.

    Ich addiere zwei Zweierkomplementzahlen. Kann es sein, dass das Ergebnis nicht mehr im Zweierkomplement ist?? Dann würde es auch Sinn machen, warum die Zahl mit 1 beginnt und trotzdem positiv ist 🙂

    Wenn Du die Zweierkomplementwelt verlassen würdest, also als Klassennamen R0 bis R255 nehmen würdest, hättest Du kein Problem, das MSB wäre halt gesetzt, woran Du erkennst, daß das Ergebnis über 127 ist. Es wäre kein Überlauf eingetreten.

    Aber wenn Du die Zweierkomplementwelt nicht verläßt, hast Du ein Problem, nämlich daß Du genau schaun muß, was passiert ist. Es wäre sozudsagen ein "Überlauf" eingetreten, daß die Zahl ins Vorzeichenbit reingelaufen ist.
    67 + 68 = 135
    Und bei 135 ist das MSB gesetzt. Die Klasse, wo 135 drin vorkommt, ist die Klasse mit …-377,-121,135,391…
    Du weißt nur, daß das Ergebnis in dieser Klasse ist, weißt aber nicht wirklich, welche Zahl davon es ist.
    Und mit negativen Zahlen nehmen wir als Repräsentanten eben nicht die 135, sondern die -121.
    Du weißt also nur, R67 + R68 = R-121, also das Ergebnis ist irgend ein -121+z*256. Das stimmt ja auch.

    Es juckt uns nicht, daß da ein "Rechenfehler" war. So rechnet der Computer nunmal, wenn er auf 8-Bit-Zahlen beschränkt ist.

    Profis schreiben nicht R67 + R68 = R-121, das habe ich nur mal zur Verdeutlicung gemacht.

    Sie schreiben irgendwo "Ab jetzt alles mod 256" oder "Ab jetzt in Z/256" und ab dann ist mit 89 automatisch die ganze Klasse R89 gemeint.
    Oder sie sagen es nichtmal dazu, sondern setzen es voraus, wenn es Computerzahlen sind.
    Deswegen ist immer je nach Kontest 67 + 68 = 135 oder 67 + 68 = -121 und das andere falsch und zwei Sätze weiter ist es auf einmal doch richtig. Und dazu kommt noch, daß unklar ist, ob es jetzt gerade um R0 bis R255 oder um R-128 bis R127 geht. Das weiß ich wenigstens nie, wenn Du was vorrechnest.


Log in to reply