So, nachdem J ja gerade (wenn auch mit Schönheitsfehler *hust*) die Speicherung natürlicher/positiver Zahlen in einem Computer erklärt hat, wäre die logische Fortsetzung die Frage, wie ganze (also auch negative) und reelle Zahlen (Kommazahlen) in einem Computer gespeichert werden. Da für die Kommazahlen die ganzen Zahlen gebraucht werden, hier erstmal

Darstellung ganzer Zahlen

Dabei gibt es unterschiedliche Möglichkeiten, jede mit eigenen Vor- und Nachteilen.

Darstellung durch Vorzeichen und Betrag:
Die wohl intuitivste Darstellung, die Zahl wird einfach mit einem zusätzlichen Bit ausgestattet, dass das Vorzeichen darstellt. Dabei bedeutet 0 "+" und 1 "-". Beispiel: -18, bei 1 Byte Wortlänge: "1 0010010"
Es gibt mehrere Nachteile dabei, z.B. dass die 0 sowohl positiv als auch negativ dargestellt werden kann, was bei Vergleichsoperationen ein getrenntes Behandeln der Null erfordert, da sonst "+0 != -0" gelten könnte. Außerdem muss bei Rechen- und Vergleichsoperationen das Vorzeichen getrennt behandelt werden.

Exzessdarstellung:
Dabei wird zu der Zahl ein fixer Wert dazuaddiert, üblicherweise etwa die Hälfte der höchsten (mit dieser Bitanzahl) darstellbaren Zahl. Im Fall von 1 Byte Wortlänge also 127. Somit sind damit Zahlen von -127 (Darstellung: 00000000) bis +128 (Darstellung: 11111111) darstellbar. Die Darstellung der 0 wäre damit 01111111 (=127).
Vorteile: Nur eine Darstellung der Null
die Darstellung ist ordnungserhaltend (kleinere Zahlen bleiben kleiner, wichtig für Vergleichsoperationen)
Nachteile: Bei arithmetischen Operationen muss der Exzess berücksichtigt werden, beispielsweise muss er vom Ergebnis einer Addition wieder abgezogen werden, da er sonst doppelt dazuaddiert würde.

Einerkomplementdarstellung:
Ein umrechnunstechnisch sehr dankbares System, da eine negative Zahl einfach aus der positiven besteht, bei der sämtliche Ziffern gespiegelt wurden. Beispiel:
Code:
+44: "00101100"
-44: "11010011"
Nachteile: Wieder doppelte Darstellung der 0; Ordnung bleibt zwar innerhalb der positiven/negativen Zahlen erhalten, jedoch sind negative Zahlen "größer" als positive; zusätzlicher Rechenaufwand bei arithmetischen Operationen durch doppelte Null-Darstellung

Zweierkomplement:
Die Zahl wird wie beim Einerkomplement gebildet, danach wird noch 1 dazugezählt. Beispiel:
Code:
+44: "00101100"
-44: "11010100"
Dadurch ergibt sich eine eindeutige Darstellung der 0 und daher auch ein geringerer Rechenaufwand bei arithmetischen Operationen.

In der Praxis werden (AFAIK) zumeist das Zweierkomplement und die Exzessdarstellung verwendet.


Kommazahlen

Etwas komplizierter ist die Darstellung von Kommazahlen. Dabei gibt es grundsätzlich zwei Ansätze, den logischeren und den besseren. ^^

Fixkommadarstellung*:
Das ist die Darstellung, die wohl auf Anhieb am logischsten erscheint. Es werden einfach für jede Zahl eine bestimmte Anzahl an Vor- und Nachkommastellen gespeichert. Eine Fixkommazahl aus 4 Byte (32 Bit) könnte demnach so aussehen:
Code:
Z VVVVVVVVVVVVVVVVV NNNNNNNNNNNNNNN
1 01010001011011110 010111010101000
Wobei Z für das Vorzeichen (0: +; 1: -), V für die Vorkomma- und N für die Nachkommastellen steht. Die dargstellte Zahl wäre in diesem Fall - 41 694,364501953125.
Der Wertebereich einer solchen Fixkommazahl (16 Vor-, 15 Nachkommastellen) aus 4 Bytes läge zwischen +/- 65535,999969482421875.
* Ich will hier gleich darauf hinweisen, dass meist von Fixpunktzahlen gesprochen wird, da im Englischen ja ein Punkt statt eines Kommas gemacht wird. Ist mir aber egal.

Diese Darstellung hat einige Vorteile, vor allem den, dass der Prozessor nicht viel umrechnen muss, um mit den Zahlen sinnvoll operieren zu können. Die Zahlen können einfach wie ganze Zahlen addiert oder subtrahiert werden. Bei Multiplikationen ebenso, nur dass dann das Ergebnis durch den jeweiligen Skalierungsfaktor (bei dem Beispiel mit 15 Nachkommastellen: 2^15) dividiert werden muss. Bei Divisionen muss anschließend mit dem jeweiligen Faktor multipliziert werden.

Jedoch hat die Darstellung den großen Nachteil, dass sie sehr unflexibel ist. Wenn man mit dem gleichen System sehr große Zahlen (> 1 Billion) und sehr kleine (ein Billionstel) speichern will, braucht man dafür vergleichsweise viel Speicherplatz, da dafür jeweils 40 Vor- und Nachkommastellen nötig wären. Das ist aber eigentlich unnötig, da man bei einer Zahl in Billionenhöhe nicht unbedingt 40 Nachkommastellen braucht, ebenso wie bei einem Billionstel kein Mensch 40 Stellen zur Darstellung der 0 vor dem Komma will. Daher findet - trotz ebenso vorhandener Nachteile - fast ausschließlich das andere System noch Verwendung:

Gleitkommadarstellung:
Bei dieser Darstellung wird die Zahl als Produkt von Mantisse und Skalierung dargestellt. Zum Beispiel kann man die Zahl 1000 auch als 10^3 und die Zahl 3000 demnach als 3 * 10^3 darstellen. Im Computerbereich wird dabei allerdings meist 2 als Basis gewählt, aufgrund der leichteren Realisierung einer Division binärer Zahlen durch diesen Faktor. Demnach wäre z.B. 24 gleich 1,5 * 2^4, oder in binärer Schreibweise: 11000 = 1,1 * 2^4. Wie man sehen kann (wenn man sich nur anstrengt ) wurde einfach das Komma um vier Stellen nach links verschoben und der Exponent von 2 um 4 erhöht. Analog wäre (gleich binär geschrieben) 0,001001 = 1,001 * 2^(-3). Dadurch ergibt sich ein deutlich platzsparenderes Format für Kommazahlen. Wenn man wieder von einem 4 Byte langen Wert ausgeht, ergäbe sich beispielsweise folgende Darstellung:
Code:
Z EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
1 10001110 10100010110111100101110
Z: Vorzeichen
0 steht wieder für eine positive, 1 für eine negative Zahl.
E: Exponent
Der Exponent wird als ganze Zahl in Exzessdarstellung abgespeichert. In diesem Beispiel beträgt der Exzess 127, was einen Wert von 15 für den Exponenten bedeutet.
M: Mantisse
Diese wird als Fixpunktzahl gespeichert, wobei die erste und einzige Vorkommastelle -laut Konvention - immer 1 betragen muss. Ist das nicht der Fall, spricht man von einer "denormierten" Gleitkommazahl. Da bei einer normierten Gleitpunktzahl die erste Stelle der Mantisse immer 1 sein muss, wird auf ihre explizite Angabe zugunsten einer größeren Genauigkeit normalerweise verzichtet. Daher wäre die korrekte Darstellung eigentlich:
Code:
Z EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
1 10001110 01000101101111001011101
Daraus ergibt sich, dass die dargestellte Zahl wieder - 41 694,36... ist, jedoch diesmal aufgrund der anderen Darstellung mit geringfügig weniger Nachkommastellen.
Man wandelt also eine Fixkommazahl in eine Gleitkommazahl um, indem man das Komma soweit verschiebt, dass die einzige Vorkommastelle eine 1 ist. Der Exponent wird dann entsprechend der Anzahl der verschobenen Stellen in Exzessdarstellung angegeben.

Daraus ergeben sich einerseits ein deutlich größerer Zahlenbereich, nämlich von +/- 2^128 maximal und +/- 2^(-127) minimal, aber auch einige Probleme:
1) Die Null ist nicht darstellbar. Das ist recht blöd, da ein Zahlensystem ohne 0 natrülich wenig Sinn macht. Daher ist die Konvention, die Null durch eine Mantisse mit lauter Nullen und einen Exponenten eins unter dem minimalen darzustellen. Dadurch ist der minimale Exponent bei einem Exzess von 127 "00000001", der Wert "00000000" ist ein Spezialwert, der bedeutet, dass die erste Stelle der Mantisse 0 ist.
2) Im Bereich um 0 bleibt aufgrund der Normierungsbedingung eine große undarstellbare Lücke. Das lässt sich ebenfalls mit dem Spezialwert lösen, da ja beim Exponenten -127 die erste Stelle der Mantisse als 0 angenommen wird. Dadurch vergrößert sich die Präzision der Gleitkommazahlen in der Nähe der Null weiter.

Für eine konkrete, genau definierte Implementierung sind weiters noch die Rundungsvorschriften wichtig, da ja längst nicht alle reellen Zahlen darstellbar sind. Daher mal im Folgenden die IEEE Norm 754, die Gleitpunktzahlensysteme normiert:

Erstmal definiert die Norm zwei Systeme, eins mit einfacher und eins mit doppelter Genauigkeit (Single/Double Precision).
Single: Bits: 32; Mantissenstellen: 23, plus implizites erstes Bit (also das erste Bit der Mantisse wird nicht geschrieben, sondern immer asl 1 angenommen); Exponentenstellen: 8; Minimaler/Maximaler Exponent: -126/+127; Exzess des Exponenten: 127.
Double: Bits: 64; Mantissenstellen: 52, plus implizites erstes Bit; Exponentenstellen: 11; Minimaler/Maximaler Exponent: -1022/+1023; Exzess des Expnenten: 1023.
Zusätzlich werden auch erweiterte Formate einfacher und doppelter Genauigkeit festgelegt, mit größeren Freiheiten in der Implementierung.

Weiters werden folgende Sonderzustände definiert:
Denormalisiert: Ist der Exponent eins kleiner als der minimale Exponent und die Mantisse ungleich 0, so handelt es sich um eine denormalisierte Gleitkommazahl, das implizite erste Bit hat also den Wert 0. Der Exponent ist allerdings trotzdem der minimale Exponent, und nicht der eins kleinere.
Null: Ist der Exponent eins kleiner als der minimale Exponent und die Mantisse ist 0, dann ist der Wert der dargestellten Zahl gleich 0. Die Darstellung besteht übrigens aus lauter Nullen, was sie auch recht intuitiv macht.
Allerdings gibt es auch hier, wie bei manchen Ganzzahlendarstellungen Werte für +0 und -0. Daher legt die IEEE Norm fest, dass dafür die Eigenschaft "-0 = +0" gilt. Jedoch wird das Vorzeichen trotzdem nicht komplett ignoriert, wodurch z.B. bei Divisionen durch Null je nach Vorzeichen +/- unendlich herauskommt.
Unendlich: Es wird auch ein Wert für den Fall bestimmt, dass die Zahl größer/kleiner ist, als die größte darstellbare, also Werte, die quasi +/- unendlich darstellen. Dazu wird der höchste Exponent genommen, eins höher als der maximal erlaubte. Die Mantisse besteht wie bei der Null aus lauter Nullen, das Vorzeichenbit unterscheidet zwischen +/- unendlich.
Nan (Not a Number): Dieser Wert wird verwendet, um das Ergebnis einer ungültigen Operation darzustellen, wie beispielsweise 0/0 oder die Wurzel aus einer negativen Zahl. Codiert wird NaN mit dem gleichen Exponenten wie Unendlich, aber mit einer Mantisse ungleich 0. Außerdem wird festgelegt, dass alle arithmetrischen Operationen mit NaN wieder NaN zurückliefern, so dass die Information über eine falsche Operation auch bei längeren Rechenvorgängen immer erhalten bleibt.

Rundung: Laut IEEE-Norm sollen alle Prozessoren als Standard die "Round to nearest"-Methode verwenden, in Verbindung mit "Round to even".
"Round to nearest" heißt, wie der Name schon sagt, dass auf den nächstliegenden darstellbaren Wert gerundet wird. "Round to even" wird eingesetzt, wenn zwei darstellbare Zahlen genau gleich weit weg von der eigentlichen Zahl liegen. Dann wird auf diejenige der beiden Zahlen gerundet, deren letzte Mantissenstelle 0 ist (= die gerade ist).
Weiters gibt es noch die Verfahren "Truncate" (alle Stellen, die auf die letzte darstellbare folgen, werden abgeschnitten) und gerichtetes Runden (Auf-/Abrunden, dürfte klar sein), die laut IEEE als aktivierbare Optionen vorhanden sein müssen.



OK, soweit zur Darstellung von Gleitkommazahlen, ich hoffe mal, ich habe nichts Wichtiges vergessen/falsch geschrieben. o_O Die Gleitkommaarithmetik hebe ich mir oder wem anderen mal als besonderes Schmankerl für später auf. Wenn irgendwas unklar sein sollte: fragt, oder noch besser, googelt. "IEEE Floating Point" liefert hunderte guter Ergebnisse.

@ Mods: Falls ihr Fehler findet, bitte bessert sie gleich aus. ^^'' Ich hab jetzt negative und Komma-Zahlen in einem gepostet, kann man ja noch immer ändern, wenn's getrennt sein sollte.