Binäre Datentypen
Diese Seite oder Abschnitt ist zwar komplett, es wird aber folgende Verbesserungen gewünscht: Fließkommazahlen beschreiben Hilf Lowlevel, den Artikel zu verbessern. |
Inhaltsverzeichnis
Einführung in Zahlensysteme
Bevor wir uns mit den einzelnen Datentypen beschäftigen ist es notwendig, dass wir generell verstehen wie Dualzahlen (Binärzahlen) aufgebaut sind.
Dezimalzahlen
Betrachten wir zunächst eine Zahl aus dem Zahlensystem mit dem wir wohl alle aufgewachsen sind: Das Dezimalsystem.
3458
Man schreibt auch
3458(10)
um zu verdeutlichen, dass eine Zahl aus dem Dezimalsystem (10er-System) gemeint ist, um Verwechslungen mit anderen Zahlensystemen auszuschließen.
Ebenfalls aus der Schule bekannt sein sollte folgende Schreibweise:
3458(10) = 3*1000 + 4*100 + 5*10 + 8*1
Nun wir befinden uns im Dezimalsystem und es fällt auf, dass „zufällig“ jeder 2. Faktor der Produkte als eine Potenz von 10 darstellbar ist:
3458(10) = 3*103 + 4*102 + 5*101 + 8*100
Dualzahlen
Das Dualsystem funktioniert ganz genauso, nur mit dem Unterschied, dass keine 10er-Potenzen benutzt werden, sondern 2er-Potenzen. Also:
10101(2) = 1*24 + 0*23 + 1*22 + 0*21 + 1*20 = 16 + 0 + 4 + 0 + 1 = 21(10)
Nebenbei kann man an diesem Beispiel auch gut sehen, wie man Dualzahlen in das Dezimalsystem konvertieren kann.
MSB und LSB
Das MSB (Most Significant Bit) und das LSB (Least Significant Bit) sind die Bezeichnungen von zwei besonderen Bits einer Dualzahl.
Das MSB ist das höchstwertige Bit. D. h. das Bit einer Dualzahl mit der höchsten 2er-Potenz.
Das LSB ist das niedrigwertigste Bit, d. h. immer das Bit mit der Wertigkeit 20.
110010(2)
Codierung
Begriffserklärung
Codierung – jeder hat wahrscheinlich diesen Begriff schonmal gehört. Aber was bedeutet „Codierung“ eigentlich? Schauen wir uns an, was die große Wikipedia dazu sagt:
Im Allgemeinen ist ein Code eine Vereinbarung über einen Satz (eine Menge) von Symbolen […] zum Zweck des Informationsaustauschs.
Was heißt das nun?
Ich bin mir sicher, dass du dir sicher schonmal (als Kind) darüber Gedanken gemacht hast warum ein Baum „Baum“ heißt und nicht „Stuhl“. Wahrscheinlich hast du von deinen Eltern die Antwort bekommen, dass es eben so sei.
Nun, als du damals gelernt hast zu sprechen, da hast du erstmal eine ganze Weile nur deinen Eltern zugehört. Und aus dem jeweiligen Zusammenhang heraus hast du dir gemerkt, dass ein „Baum“ sowas ist, was meistens draußen rumsteht, einen braunen Stamm hat, mit Ästen und (meistens) grünen Blätteren dran. Du hast also das Wort, bzw. damals wohl eher nur den Laut, den deine Eltern gemacht haben, als sie beispielsweise auf einen Baum gezeigt haben, mit diesem Objekt assoziiert, was da draußen im Garten stand.
Und das war schon eine Codierung. Du hast einem an sich bedeutungslosen Laut, der erzeugt wird, wenn Menschen „Baum“ sagen, eine Bedeutung gegeben.
Man kann also genauso einen eigenen Code erzeugen, den dann jeder verstehen kann, der dessen Bedeutung kennt, mit dem du also eine Bedeutung vereinbart (--> siehe Zitat aus Wikipedia) hast.
Vereinbaren wir also
Code | Bedeutung |
---|---|
„Harry“ | Du |
„Blumen“ | abwaschen |
„kauft“ | musst |
„rote“ | nicht |
Wenn du jetzt also mit jemandem diese Codierung vereinbarst und ihm dann sagst:
Harry kauft Blumen
Dann weiß diese Person, dass sie abwaschen muss. (==> Du musst abwaschen)
Harry kauft rote Blumen
würde dementsprechend bedeuten, dass die angesprochene Person nicht abwaschen muss (==> Du musst nicht abwaschen) Allerdings wird dich wahrscheinlich jeder, der diese Code nicht kennt, nur fragend anschauen.
Codierung von (Dual)Zahlen
Wie oben schon erklärt bzw. angedeutet sind Dualzahlen so codiert, dass der Wert einer Dualzahl die Summe aller Produkte der i-ten Ziffer (i = 0 – n) mit 2i
Hier eine Tabelle mit der Codierung aller 3-Bit Zahlen.
Code | Wert (Summe) | Wert |
---|---|---|
000(2) | 0*22 + 0*21 + 0*20 | 0(10) |
001(2) | 0*22 + 0*21 + 1*20 | 1(10) |
010(2) | 0*22 + 1*21 + 0*20 | 2(10) |
011(2) | 0*22 + 1*21 + 1*20 | 3(10) |
100(2) | 1*22 + 0*21 + 0*20 | 4(10) |
101(2) | 1*22 + 0*21 + 1*20 | 5(10) |
110(2) | 1*22 + 1*21 + 0*20 | 6(10) |
111(2) | 1*22 + 1*21 + 1*20 | 7(10) |
Analoges gilt natürlich wie oben beschrieben auch für alle längeren Dualzahlen.
Genauso könnte man aber auch folgendes vereinbaren (d. h. codieren)
Code | Wert |
---|---|
000(2) | -3(10) |
001(2) | -2(10) |
010(2) | -1(10) |
011(2) | 0(10) |
100(2) | 1(10) |
101(2) | 2(10) |
110(2) | 3(10) |
111(2) | 4(10) |
Wir kommen der Sache schon näher. Wir habe nämlich soeben mit 3 Bit die Zahlen von -3 bis 4 codiert. Ein erster Schritt in die richtige Richtung!
Natürliche Zahlen
Natürliche Zahlen sind die Zahlen, die wir wohl alle noch aus der Grundschule kennen. Die Menge der natürlichen Zahlen enthält alle positiven Zahlen inklusive der 0. Diese Zahlen lassen sich in binärer Darstellung wunderbar darstellen, denn die Codierung entspricht der „Standard-Codierung“ mit den 2er-Potenzen.
Ganze Zahlen
Lineare Codierung
Oben hatte ich bereits eine Codierung vorgestellt, die in 3 Bit die Zahlen -3 bis +4 codiert hat. Dabei wurde eine untere Grenze gewählt (in dem Fall -3) und dann wurde „hochgezählt“ bis wir schließlich dem letzten Code (111(2)) den Wert 4 zugeordnet hatten.
Das scheint erstmal ganz gut zu funktionieren. Ist aber dennoch etwas unübersichtlich und die -3 kann mit dieser Methode in einer n-Bit-Codierung schon ganz anders aussehen. Das nächste Problem ist, dass man mit dieser Codierung nicht ohne weiteres rechnen kann.
Nehmen wir aus obiger Tabelle folgende Zahlen und addieren sie:
010 (=-1) +011 (= 0) --------- 101 (= 2)
Offensichtlich scheint das Ergebnis nicht ganz zu stimmen.
Das Vorzeichenbit
Nunja. Allein aus Gründen der Übersichtlichkeit war unser erster Versuch nicht besonders schön. Eine gute Idee wäre es doch 1 Bit zu reservieren, welches das Vorzeichen angibt.
Also codieren wir unsere ganzen Zahlen nun folgendermaßen:
Das MSB einer n Bit langen Binärkette stellt das Vorzeichen dar.
Vorzeichenbit | Bedeutung |
---|---|
0(2) | positive Zahl |
1(2) | negative Zahl |
Die restlichen n-1 Bits stellen den Betrag der Zahl dar. Der Betrag wird wie eine natürliche Zahl codiert.
Also sieht eine (in diesem Fall 4-Bit) Zahl mit dieser Codierung allgemein so aus:
VBBB
Beispiele:
1100 = -4 0011 = +3
Sieht doch gut aus oder? Vorallem recht einprägsam. Allerdings muss ich euch mitteilen, dass auch dies nicht die Lösung ist. Denn schauen wir mal was geschieht wenn wir die beiden Zahlen oben aus dem Beispiel addieren:
1100 (-4) +0011 (+3) --------- 1111 (-7)
Nun, da hätte -1 rauskommen sollen. Also anscheinend auch nicht geeignet für arithmetische Operationen. Andererseits schaut euch mal diese beiden Zahlen an:
0000 = -0 1000 = +0
Seltsam, oder? Selbst wenn die Addition erfolgreich gewesen wäre, dann wäre diese Phänomen immer noch sehr fragwürdig.
Das Einerkomplement
Die Sache mit dem Vorzeichenbit hat immer noch ein Problem.
Was machen wir, wenn wir die Zahl der Bits vergrößern wollen?
Wir müssen immer wissen, das MSB nicht zur Zahl selber, sondern zum Vorzeichen gehört.
Denn: 1011 ist -3 Aber: 00001011 ist 11 Es müsst aber heißen: 10000011 ist 11
Das kopieren eines einzelnen Bits ist ziemlich aufwendig. Also probieren wir doch mal folgenes:
Wir sagen einfach:
Bedeutung | Darstellung |
---|---|
positive Zahl | einfache Binärzahl wobei das MSB 0 bleiben sollte |
1(2) | Logisches Komplent des Betrags. |
Also zum Beispiel:
0100 = +4 1011 = -4 0011 = +3
Dadurch das das logische Komplement des MSB 1 ergeben muss, lässt sich das Vorzeichen dort ablesen.
Die Addition funktioniert doch schon ganz gut:
1011 (-4) 1001 (-6) +0011 (+3) +0011 (+3) --------- ---------- 1110 (-1) 1100 (-3)
Aber wehe man überschreitet den Nullpunkt (Wir schmeißen den Übertrag raus):
1100 (-3) 1001 (-6) +0101 (+5) +0111 (+7) --------- ---------- 0001 (+1) 0000 (+0)
Das Problem ist klar. Sobald man versucht, 0 zu überschreiten, wird das Ergebnis um eins kleiner als es sein sollte. Ist ja auch logisch, schließlich liegen zwischen -1 und 1 auch zwei Zahlen, nämlich:
1111 = -0 0000 = +0
Wir müssen also versuchen wie wir das Problem gelöst bekommen.
Das Zweierkomplement
Ich hoffe, ihr habt noch nicht die Hoffnung aufgegeben eine geeignete Codierung für ganze Zahlen zu finden – ich kann euch beruhigen: Dieser Ansatz wird zum Erfolg führen!
Das mit dem Einerkomplement war schon kleine Schlechte Idee. Was ist, wenn wir einfach sagen, das man zu jeder negativen Zahl die fehlenden 1 schon mal nach dem Komplementieren dazu zählen?
Dann haben wir das Zweierkomplement (2k)
Wir müssen also folgendes tun:
- Binärkette negieren
- 1 draufaddieren
Praktischerweise ergibt sich bei dieser Codierung, dass das MSB negativer Zahlen 1 und das von positiven Zahlen gleich 0 ist, da ja das Vorzeichen nur bei -0 (1111) zu 0000 gewechselt wird. (0 ist also immer eine Positive Zahl)
Beispiel
Angenommen wir haben die 4-Bit-2k-Zahl 5(10) = 0101(2) Wir wollen diese nun negieren:
1) Binärkette negieren:
0101 --> 1010
2) 1 draufaddieren
1010 +0001 ----- 1011
Ergebnis: 1011(2) = -5(10)
Durch das selbe Verfahren lässt sich aus der -5 auch wieder die +5 gewinnen!
Wenn wir das ganze zu Fuß machen wollen, gibt es da noch einen Weg:
- Alle Bits vom LSB bis zum ersten gesetzten Bit (=1) einschließlich übernehmen.
- Alle höherwertigen Bits negieren.
Fließkommazahlen
TODO
Strings
Strings, zu Deutsch „Zeichenketten“, sind Aneinanderreihungen von ASCII-Zeichen.
C-Strings
In dieser Variante, die von C genutzt wird, werden die Zeichen einfach hintereinander in einem linearen Speicher abgelegt. Das Ende des Strings wird durch ein Nullzeichen (\0) markiert. Somit ist ein String in C im Grunde ein Char-Array.
Wenn man in C eine Stringkonstante definiert, wird das abschließende Nullzeichen automtisch angehängt. Dennoch sollte immer darauf geachtet werden, dass nicht in unerlaubte Speicherbereiche geschrieben wird, falls ein Programm dieses Nullzeichen weglässt.
„LowLevel“ in C:
Index: 0-1-2-3-4-5-6-7-8 Inhalt: L o w L e v e l 0
Pascal-Strings
In der Pascal-Variante ist ein String ebenfalls ein Char-Array. Allerdings wird die Länge des Strings im nullten Element gespeichert, der eigentliche Text beginnt erst beim ersten Element.
„LowLevel“ in Pascal:
Index: 0-1-2-3-4-5-6-7-8 Inhalt: 8 L o w L e v e l