…oder warum 10 auch 2 sein kann
Ohne das Verständnis der drei gebräuchlisten Zahlensysteme im Computer-Bereich (Dezimales-, Binäres- und Hexadezimales-Zahlensystem) wird man bei der Programmierung nicht sehr weit kommen. Daher hier eine kleine Einführung.
Der interessierte Leser wird erfreut sein, dass das erste Zahlensystem ihm schon bekannt ist, das hoffe ich jedenfalls. 😉
1. Dezimalsystem
Unser vertrautes Dezimalsystem beruht bekanntlich auf den Ziffern 0123456789. Wir alle sollten im Umgang damit vertraut sein.
Die Zahl 1984 (eintausend-neunhundert-vierundachtzig) stellt zunächst kein Hinderniss dar. Wir können sie lesen und damit rechnen, sechs dazu oder vierzehn weniger sollten kein Problem sein.
Um die weiteren Zahlensysteme besser zu verstehen möchte ich hier eine mehr mathematische schreibweise aufzeigen.
1 9 8 4 1*10^3 + 9*10^2 + 8*10^1 + 4*10^0 1*1000 + 9*100 + 8*10 + 4*1 1000 + 900 + 80 + 4 1984
Die schreibweise mit * und ^ mag den Einen oder Anderen verschrecken, aber so sieht es in einigen Programmiersprachen tatsächlich aus. Selbst schuld, du wolltest ja unbedingt programmieren. 😉
Der Stern * entspricht der Multiplikation (Malzeichen) und das Dach ^ bedeutet hoch, also ist 5*7=35 und 4^3=4*4*4=64.
Allgemein kann man also sagen, dass sich eine Zahl im Dezimalsystem auch als „mal 10 hoch <(Position [n] von rechts) – 1>“ darstellen läßt oder als Formel x*10^(n-1).
Da jede Stelle (bzw. Ziffer) zehn Möglichkeiten bietet (0-9) hat das Dezimalsystem also die Basis [b] 10 (lustige Randnotiz, kaum zu glauben, aber Dezi bedeutet doch tatsächlich zehn).
2. Binärsystem
Vor einigen Jahren schickte mir ein Freund eine E-Mail mit dem Inhalt…
Es gibt genau 10 „Arten“ von Menschen: Die, die Binärzahlen verstehen und die, die sie nicht verstehen.
Das Binärsystem ist wohl das wichtigste und vorallem grundlegenste Zahlensystem im Computerbereich. Ein Prozessor besteht im Prinzip nur aus einer riesigen Ansammlung von Schaltern (Transistoren). Ist ein Schalter geöffnet, kann kein Strom fließen (dies wird als 0 dargestellt) bzw. ist ein Schalter geschlossen, dann fließt Strom (Überraschung, dafür steht die 1).
Damit haben wir uns auch schon die Basis des Binärsystems erarbeitet. Es gibt je Stelle (bzw. Ziffer) nur zwei Möglichkeiten (0 oder 1), daher hat es die Basis [b] 2. Eine einzelne Stelle / Ziffer wird Bit (aus dem engl. BInary digiT; binary = binär = zwei Zustände) genannt, bitte nicht mit dem Bier verwechseln 😉 .
Da man mit hunderten Nullen und Einsen (Bits) am Stück wenig anfangen kann, werden diese in logische Gruppen zusammengefasst. Die bekannteste nennt sich Byte und besteht aus 8-Bits. Wie wichtig dies ist, erkennt man daran, dass der C64 ein sog. 8-Bit Rechner ist.
Wie sehen nun Zahlen im Binärsystem aus?
Uns werden immer wieder Darstellungen wie %00101010 begegnen. Das Prozentzeichen dient häufig als Kennzeichen für eine Binärzahl. Wenn wir nun unsere Formel von oben x*10^(n-1) um eine weitere Variable ergänzen, dann können wir auch Binärzahlen umrechnen. Die 10 wird mit [b] für die Basis ersetzt und schon haben wir eine universell gültige Formel um unsere Zahlensystemen umzurechnen.
Somit lautet unsere Formel: x*b^(n-1)
Wenden wir diese doch direkt mal auf %00101010 an.
0 0 1 0 1 0 1 0 0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0 0 + 0 + 32 + 0 + 8 + 0 + 2 + 0
Somit entspricht %00101010 der Dezimalzahl 42 (danke für den Fisch).
Binärzahlen lassen sich sehr einfach im Kopf umrechnen. Mit der Wertigkeit eins von rechts beginnend, hat jedes Bit die doppelte Wertigkeit des vorherigen. Nun braucht man nur die Werte zu addieren bei denen das Bit gesetzt ist, also wo eine 1 steht.
Sehen wir uns mal ein BYTE mit lauter Einsen %11111111 an:
Pos. 8 7 6 5 4 3 2 1 Bit 1 1 1 1 1 1 1 1 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
Addieren wir nun alle ermittelten Werte (128+64+32+16+8+4+2+1) erhalten wir 255. Dies ist die größte, mit einem Byte darstellbare Zahl. Nehmen wir noch den Fall, dass alle BITs = 0 sind hinzu, so kommen wir auf 256 mögliche Zahlen (von 0 bis 255), die mit einem Byte darstellbar sind.
Wie man Binärzahlen mit AND, OR, EOR (bzw. XOR) und NOT „manipuliert“, wird im nächsten Beitrag Boolsche Algebra beschrieben.
Wichtig: Spricht man davon, das Xte BIT zu setzen / prüfen, immer daran denken, dass die Zählung von rechts beginnt!
Außerdem werden die BITs in der Praxis von 0 (ganz rechts) bis 7 (ganz links) durchnummeriert.
Bits lassen sich nicht nur zu Bytes zusammenfassen, begegnen werden uns noch folgende „Gruppen“:
- Nibble (damit ist kein Schweinkram gemeint): halbes Byte = 4-Bit
- Byte: 8-Bit
- Word: 2-Byte; 16-Bit
- DWord (DoubleWord) / LWord (LongWord): 2-Word; 4-Byte; 32-Bit
Jetzt sollte auch klar sein, warum 10 manchmal 2 ist.
3. Hexadezimalessystem
Da Programmierer schreibfaul sind und das Binärsystem mit der Basis [b] 2 nicht so schön ins Dezimalsystem passt, wurde das Hexadezimalezahlensystem geschaffen. Dieses erlaubt es je Stelle / Ziffer ein Nibble abzubilden. Wie wir oben gelernt haben, besteht ein Nibble aus 4-Bit, somit lassen sich mit einer zweistelligen Hex-Zahl (ich kürze Hexadezimaleszahlensystem nun ab) Zahlen von 0 bis 255 darstellen.
Wie funktioniert das?
Jeder Dezimalzahl des Nibbles, wird eine „Hex-Ziffer“ zugewiesen. Zunächst ist dies nicht weiter schwer: 0, 1, 2, 3, 4, 5, 6, 7, 8 und 9 bleiben einfach erhalten, aber was ist mit 10, 11 ,12, 13, 14 und 15? Hierfür wurden einfach die ersten sechs Buchstaben des Alphabets (A, B, C, D, E und F) genommen.
Schauen wir uns das mal in einer Tabelle genauer an.
Nibble Dezimal Hex %0000 0 $0 %0001 1 $1 %0010 2 $2 %0011 3 $3 %0100 4 $4 %0101 5 $5 %0110 6 $6 %0111 7 $7 %1000 8 $8 %1001 9 $9 %1010 10 $A %1011 11 $B %1100 12 $C %1101 13 $D %1110 14 $E %1111 15 $F
Als erstes sollte euch das Dollarzeichen $ auffallen, dies wird häufig zur Kennzeichnung von Hex-Zahlen verwendet. Nun sollte z. B. die Umwandlung unserer Binärzahl %00101010 ins Hex-Format nicht mehr schwerfallen. Dazu trennen wir das Byte einfach in die beiden Nibble %0010 und %1010. Ermitteln die Dezimalzahlen für jedes Nibble (also 2 und 10) und suchen uns die dazugehörigen Hex-Ziffern $2 und $A heraus. Diese können nun einfach als eine Hex-Zahl $2A betrachtet werden.
%00101010 = $2A = 42
Jetzt wisst ihr auch, warum die Kennzeichnung der unterschiedlichen Zahlensystem so wichtig ist!
Wie sollte man sonst 10; %10 und $10 unterscheiden?
Wie sieht es nun mit unserer schlauen Formel x*b^(n-1) aus? Die Basis [b] ist hier 16, da jede Stelle / Ziffer sechzehn (0-9 & A-F) verschiedene Möglichkeiten bietet.
Nehmen wir als Beispiel mal das Word $07C0.
$ 0 7 C 0 0*16^3 + 7*16^2 + 12*16^1 + 0*16^0 0 + 1792 + 192 + 0 1984
Um aus unserer Hex-Zahl $07C0 eine Binärzahl zu machen, brauchen wir nur jede Stelle / Ziffer als Nibble hintereinander schreiben.
$ 0 7 C 0 % 0000 0111 1100 0000
Auch wenn es nicht zwingen notwendig ist, schreibe ich bei Binär- und Hex-Zahlen führende Nullen immer bis zur nächsten logischen Gruppen-Grenze mit. Bei unserem Beispiel von eben wäre dies ein Word, daher schreibe ich $07C0 statt $7C0 und %0000011111000000 statt %11111000000. Ich finde es liest sich besser und man sieht direkt, mit welchen Größen man es an der jeweiligen Stelle im Programm zu tun hat.
4. Dezimal in Binär oder Hex umrechnen
So, wir wissen nun, wie man Bin- (Binär) und Hex-Zahlen ins Dezimal-System umrechnet und von Bin nach Hex und Hex nach Bin kommt, aber wie rechnen wir Dezimalzahlen in die anderen Systeme um?
Wie wird nun aus 42 eine Binär-Zahl?
Dazu müssen wir wieder die Basis [b] des Ziel-Systems bemühen und vorher klären, was der Modulo ist. Der Modulo ist der ganzzahlige Rest einer Division. In der Programmierung wird dieser häufig mit dem Prozentzeichen % abgebildet, nicht mit dem Binärkennzeichen zu verwechseln!
14%3 (14 Modulo 3) ergibt 2!
Da die 3 viermal komplett in die 14 passt (4*3 = 12) und somit ein Rest von 2 (14-12) übrig bleibt.
Dieser Modulo hilft uns nun, die Dezimalzahlen umzurechnen.
Schauen wir uns ein Beispiel mit der altbekannten 42 an. Um zur Bin-Zahl zu kommen, bilden wir solange den Modulo der Basis [b] 2 (0 / 1) des Binär-Systems, bis wir als ganzzahliges Ergebnis 0 erhalten.
Wir teilen also 42 durch 2, das geht glatt auf = 21, es bleibt kein Rest, wir notieren eine 0.
Nun bilden wir den Modulo für das ganzzahlige Ergebnis der vorherigen Rechnung. Also 21 durch 2 teilen, da kommen wir auf 10, behalten aber einen Rest von 1. Diesen Rest notieren wir und fahren mit 10 durch 2 fort…
Nun sollte sich diese Tabelle eigentlich selbst erklären:
Rest 42/2 = 21 -> 0 21/2 = 10 -> 1 10/2 = 5 -> 0 5/2 = 2 -> 1 2/2 = 1 -> 0 1/2 = 0 -> 1
Schreiben wir nun das, was als Rest übrigbleibt, von unten nach oben hintereinander, erhalten wir wieder unsere bekannte Bin-Zahl %101010, die wir zum besseren Lesen noch auf die Byte-Grenze auffüllen können %00101010.
Das Umwandeln von 1984 in eine Hex-Zahl läuft nahezu identisch ab, nur das hier die Basis [b] bekanntlich 16 (0-9 & A-F) ist.
1984/16 = 124 -> Rest 0 => $0 124/16 = 7 -> Rest 12 => $C 7/16 = 0 -> Rest 7 => $7
Auch hier wieder, das was als Rest übrigblieb, von unten nach oben, einfach hintereinander wegschreiben und wir bekommen $7C0 bzw. etwas lesbarer mit einer führenden Null $07C0.
Wie weiter oben bereits erwähnt, sind Programmierer auch nur Menschen und neigen zur Bequemlichkeit. Daher ist es keine Schande z. B. den Windows-Taschenrechner zu starten und diesen auf „Programmierer“ umzustellen.
Setzt ihr später das C64 Studio ein, dann findet ihr dort ebenfalls die Möglichkeit, direkt Zahlen umzurechnen.
Thank you for your cooperation.
Hey, das ist ja echt witzig. Vielen Dank für dieses tolle Tutorial. Ich war in den 80ern auch ein begeisterter C64ler und bin natürlich später ebenfalls auf den Amiga gewechselt. Ich verbinde sehr, sehr gute Stunden mit dem Brotkasten, und bin schon länger am überlegen, ob ich mir den nicht wieder anschaffen sollte.
Danke und gute Zeit!
Ups! Es muß hier natürlich ‘sechs’ lauten:
“fünf Buchstaben des Alphabets (A, B, C, D, E und F) genommen.”
Danke für den Hinweis.