Zahlensysteme

Im alltäglichen Umgang rechnen wir Menschen im sogenannten Dezimalsystem, also mit den Ziffern 0 bis 9. Da ein Computer jedoch nur die zwei Zustände Strom oder nicht-Strom unterscheiden kann, kennt er nur die Ziffern 0 und 1. Das System mit zwei Zuständen wird Binärsystem genannt.

Die limitierte Zahl an Ziffern ist jedoch kein Hindernis für mathematische Berechnungen. Diese können unabhängig des sogenannten Zahlensystems genau gleich ausgeführt werden. In der Programmierung mit C und C++ wird hauptsächlich das Dezimalsystem und in gewissen Fällen das Hexadezimalsystem (16 Ziffern) verwendet. Das Binärsystem ist nur in wenigen Compilern eingebaut, kann jedoch stets durch Bit-Operationen nachgebildet werden. Ganz am Rande spielt das Okalsystem (8 Ziffern) eine kleine Rolle in der Programmierung.

Das Dezimalsystem

Das Dezimalsystem ist dasjenige System, mit welchem wir Menschen mit unseren 10 Fingern rechnen. Mithilfe einer Aneinanderreihung der arabischen Ziffern 0 bis 9 können wir jede beliebige positive Ganzzahl schreiben. Die Anordnung der Ziffern ist jedoch nicht beliebig. Schon in der Grundschule lernen wir, Zahlen so aufzuschreiben, dass die Ziffern links höherwertiger sind als die Ziffern rechts. Hier als Beispiel die Zahl 456:

  4 * 100
+ 5 *  10
+ 6 *   1
---------
=     456

Die Hunderter, Zehner und Einer wurden als Summe von sogenannten Zehnerpotenzen dargestellt. Im folgenden werden diese Zehnerpotenzen mathematisch aufgeschrieben:

  Decimal
----------------
        1 = 10^0
       10 = 10^1
      100 = 10^2
    1'000 = 10^3
   10'000 = 10^4
  100'000 = 10^5
1'000'000 = 10^6
            etc.

Dabei wird die Zahl 10 die Basis dieses Systems genannt.

Da Menschen normalerweise mit dem Dezimalsystem rechnen, nimmt beim Programmieren in C und C++ ein Compiler bei Auftreten einer Zahl im Source-Code grundsätzlich immer das Dezimalsystem an. Um eine Zahl in einem anderen System zu schreiben, muss sie speziell gekennzeichnet werden.

Auch wenn ein Compiler grundsätzlich Dezimalzahlen annimmt, wandelt er die Zahlen während der Übersetzung in Binärzahlen um. Wie die Umwandlung von Zahlensystemen funktioniert, steht weiter unten auf dieser Seite.

Das Binärsystem

Wenn die Basis auf 2 gesetzt wird, entstehen Zweierpotenzen:

   Binary         Decimal
-------------------------
        1 = 2^0 =       1
       10 = 2^1 =       2
      100 = 2^2 =       4
     1000 = 2^3 =       8
    10000 = 2^4 =      16
   100000 = 2^5 =      32
  1000000 = 2^6 =      64
 10000000 = 2^7 =     128
100000000 = 2^8 =     256
            etc.

Wichtige Zahlen sind dabei:

2^8: Dies sind die Anzahl Zustände, die mit einem Byte und somit mit dem int8_t-Typ dargestellt werden können.

2^10: Diese Zahl wird oft für Grössenangaben benutzt. Da sie sehr nahe bei 1000 liegt, wird sie für das Kilo benutzt. Exakt gerechnet ist jedoch 2^10 = 1024. Korrekterweise wird diese Grössenangabe somit nicht Kilo, sondern Kibi (Kilobinary) genannt, allerdings wird die Unterscheidung zwischen 1000 und 1024 nur selten gemacht.

2^16: Dies sind die Anzahl Zustände, die mit zwei Bytes und somit mit dem int16_t Typ dargestellt werden können.

2^20: Diese Zahl entspricht rund einer Million und wird aufgrund ihrer Nähe zur einer Million als Mega bezeichnet. Da 2^20 jedoch nicht exakt eine Million beziffert, gibt es auch hier die korrekte Grössenangabe Mebi (Megabinary).

2^30: Diese Zahl entspricht rund 1 Milliarde und wird mit Giga bezeichnet. Korrekterweise heisst diese Grössenangabe Gibi (Gigabinary).

2^32: Dies sind die Anzahl Zustände, die mit vier Bytes und somit mit dem int32_t-Typ dargestellt werden können .

2^64: Dies sind die Anzahl Zustände, die mit acht Bytes und somit mit dem int64_t-Typ dargestellt werden können .

In C und C++ können Binärzahlen mit modernen Compilern normalerweise nicht mehr geschrieben werden. Sofern ein Compiler sie jedoch zulässt, müssen sie als Binärzahlen gekennzeichnet werden, indem der Zahl ein 0b vorne oder ein b hinten angehängt wird. Weitere Informationen zur Schreibweise können bei den festen Werten (Literalen) nachgelesen werden.

Das Hexadezimalsystem

Das Hexadezimalsystem hat die Basis 16, womit folgende Sechzehnerpotenzen entstehen:

Hexadecimal                Decimal
----------------------------------
          1 = 16^0 =             1
         10 = 16^1 =            16
        100 = 16^2 =           256
       1000 = 16^3 =         4'096
      10000 = 16^4 =        65'536
     100000 = 16^5 =     1'048'576
    1000000 = 16^6 =    16'777'216
   10000000 = 16^7 =   268'435'456
  100000000 = 16^8 = 4'294'967'296
              etc.

Das Hexadezimalsystem benötigt 16 verschiedenen Ziffern. Da die arabischen Ziffern hierfür nicht ausreichen, werden für die Werte 10 bis 15 einfach die Buchstaben a bis f genommen:

+-----+-----+------+
| Dec | Hex |  Bin |
+-----+-----+------+
|  0  |  0  | 0000 |
|  1  |  1  | 0001 |
|  2  |  2  | 0010 |
|  3  |  3  | 0011 |
|  4  |  4  | 0100 |
|  5  |  5  | 0101 |
|  6  |  6  | 0110 |
|  7  |  7  | 0111 |
|  8  |  8  | 1000 |
|  9  |  9  | 1001 |
|  10 |  a  | 1010 |
|  11 |  b  | 1011 |
|  12 |  c  | 1100 |
|  13 |  d  | 1101 |
|  14 |  e  | 1110 |
|  15 |  f  | 1111 |
+-----+-----+------+

Ob dabei die Buchstaben gross- oder kleingeschrieben sind, spielt in C und C++ keine Rolle. Um eine Hexadezimalzahl zu kennzeichnen, wird der Zahl ein 0x vorne angehängt. Weitere Informationen zur Schreibweise können bei den festen Werten (Literalen) nachgelesen werden.

Wie in der vorherigen Tabelle leicht ersichtlich ist, sind Hexadezimalzahlen und Binärzahlen eng miteinander verwandt. Jeweils vier Bits einer Binärzahl können als eine Hexadezimalzahl dargestellt werden. Nicht zuletzt aufgrund der kompakteren Schreibweise haben die Hexadezimalzahlen in der Programmierung die Binärzahlen irgendwann verdrängt.

Das Oktalsystem

Das Oktalsystem hat die Basis 8. Dieses System wird nur noch sehr selten verwendet. Beispielsweise bei der Angabe der Rechte-Flags von Dateien in einem Unix-Dateisystem oder bei der Angabe einzelner Characters mittels eines entsprechenden Escape-Codes. Letztere können bei den festen Werten (Literalen) nachgelesen werden.

Umwandlung der Systeme

Eine aufgeschriebene oder anderweitig gespeicherte Zahl besitzt mathematisch gesehen zum einen einen Wert, zum anderen eine Darstellungsform. Durch eine Wahl des Zahlensystems ändert sich nur die Darstellungsform, nicht aber der dahinterliegende Wert. Sämtliche Systeme mit zwei oder mehr Ziffern sind somit als gleichwertig zu betrachten und stets ineinander umwandelbar.

Eine Umwandlung zwischen Binärzahlen und Hexadezimalzahlen ist sehr einfach. Gemäss obiger Tabelle entsprechen jeweils vier binäre Ziffern genau einer hexadezimalen Ziffer. Bei der Umwandlung vom einen System in das andere können die Ziffern einfach durch das jeweilige Pendant ersetzt werden. Dasselbe gilt für Umwandlungen zwischen dem Oktalsystem und dem Binärsystem, die entsprechenden Bit-Folgen sind jedoch auf dieser Seite nicht aufgeführt. Für eine Umwandlung zwischen dem Oktalsystem und dem Hexadezimalsystem wird die Zahl als Zwischenschritt einfach zuerst ins Binärsystem umgewandelt.

Interessanter ist die Umwandlung zwischen dem Dezimalsystem und einem der anderen. Da die Zahl 10 selbst keine Zweierpotenz ist, existieren keine eindeutigen Ziffernfolgen, welche die dezimalen Ziffern abbilden würden. Um somit beispielsweise eine hexadezimale Zahl in eine dezimale Zahl zu verwandeln, müssen die verwendeten Sechzehnerpotenzen aufsummiert werden:

Hexadecimal: 4f36ea17

4  * 268'435'456 =   1'073'741'824
15 *  16'777'216 =     251'658'240
3  *   1'048'576 =       3'145'728
6  *      65'536 =         393'216
14 *       4'096 =          57'344
10 *         256 =           2'560
1  *          16 =              16
7  *           1 =               7
                   + -------------
Decimal:             1'328'998'935

Die umgekehrte Umwandlung muss dementsprechend auch umgekehrt vonstatten gehen:

Decimal:             1'328'998'935

1'328'998'935 / 268'435'456 =  4 remaining 255'257'111
  255'257'111 /  16'777'216 = 15 remaining   3'598'871
    3'598'871 /   1'048'576 =  3 remaining     453'143
      453'143 /      65'536 =  6 remaining      59'927
       59'927 /       4'096 = 14 remaining       2'583
        2'583 /         256 = 10 remaining          23
           23 /          16 =  1 remaining           7
            7 /           1 =  7 remaining           0

Hexadecimal: 4f36ea17

Die Dezimal-Umwandlungen kosten viel Zeit. Deswegen werden Zahlenwerte in Computern normalerweise binär gespeichert und nur für die Ein- oder Ausgabe aufs Dezimalsystem gewechselt.

Ein Beispielprogramm, welches beliebig grosse Werte ineinander umkonvertieren kann, findet sich beim Zahlensystem-Umrechner.

Nächstes Kapitel: Bits, Bytes, msb, Endianness