IT-Academy Logo
Sign Up Login Help
Home - Programmieren - Codierungen - Darstellung von Fließkommazahlen



Darstellung von Fließkommazahlen

Dieser Artikel erklärt die Darstellung von Fließkommazahlen im Rechner.


Autor: Rolf Viehmann (Rolfhub)
Datum: 29-01-2002, 22:47:33
Referenzen: IEEE-757
Schwierigkeit: Fortgeschrittene
Ansichten: 17443x
Rating: 8 (3x bewertet)

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Version dieses Dokuments: 1.1.1

Einleitung

An anderer Stelle [IT-Academy - Artikel 0000000055] habe ich bereits die Darstellung von ganzen Zahlen im Rechner erläutert (relativ weit unten im Text), aber ein Computer kennt neben ganzen Zahlen noch einen anderen Typ von Zahlen, die Fließkommazahlen, auch Gleitkommazahlen genannt. Was unterscheidet die einen von den anderen?
Nun, sehen wir uns folgende Zahl im Hexadezimalsystem an:
0xFFFFFFFFFFFFFFFF
Sie ist 16 Ziffern lang, im Dualsystem wären das also schon 64 Ziffern, der dezimale Wert liegt aber erst bei ca. 1.84 * 10 hoch 19 (wenn wir von einem Integer-Datentyp ausgehen), also noch keine sonderlich utopisch große Zahl, Wissenschaftler arbeiten oftmals mit sehr viel größeren Zahlen. Ein weiteres Problem sind gebrochene Zahlen, bei denen die Anzahl der Nachkommastellen nicht fix ist (wie z. B. bei Währungen), und die ebenfalls gespeichert werden müssen.
Es war also notwendig, ein weiteres Zahlenformat für Rechner festzulegen.

Die Idee ist folgende: Jede Zahl lässt sich in der Wissenschaftlichen Notation aufschreiben, die ich auch schon oben benutzt habe:
m * b hoch e
wobei:
m = Mantisse
b = Basis
e = Exponent

Normalerweise ist die Basis zehn, ich kann z. B.
10200
als
1.02 * 10 hoch 4
schreiben, oder anders ausgedrückt, ich verschiebe das Komma so, dass ich genau eine Ziffer vor dem Komma habe, der Rest befindet sich jetzt hinter dem Komma. Der Exponent gibt mir jetzt die Anzahl der Stellen an, um die ich das Komma verschoben habe.

Die rechnerinterne Darstellung von Fließkommazahlen ist mehr oder weniger unmittelbar aus dieser Wissenschaftlichen Notation hervorgegangen:
Der Rechner benutzt intern das Dualsystem, auch bei Fließkommazahlen, der erste Schritt ist also die Umwandlung der Dezimalzahl in das Dualsystem. Betrachten wir z. B. folgende Dualzahl:
1010100 (=84)
diese lässt sich jetzt ähnlich wie die Dezimalzahl oben schreiben als
1.0101 * 2 hoch 6
wobei die Basis 2 hier fix ist, genau wie die Basis 10 es normalerweise wäre, wenn ich wie gewohnt im Zehnersystem rechnen würde. Dies hat auch hier den Sinn, dass der Exponent einfach aussagt, um wie viele Stellen ich das Komma verschoben habe.
Uns fällt jedoch noch etwas auf: da wir fordern, dass sich genau eine Stelle (also die Höchstwertigste von Null verschiedene) vor dem Komma befindet, und diese Stelle im Dualsystem ja immer Eins (da ungleich Null) sein muss, muss diese nicht notwendigerweise gespeichert werden.

Wir müssen also nur folgende Daten speichern:

1.: Das Vorzeichen der Zahl
2.: Die Nachkommastellen der Mantisse
3.: Den Exponenten

Der Exponent kann jedoch auch negativ sein, was machen wir damit?

Es wäre denkbar gewesen, einen negativen Exponenten wie gewohnt zu speichern, wie im anderen Dokument bereits diskutiert, aber man ist hier einen anderen Weg gegangen:
Zur Speicherung des Exponenten werden eine bestimmte Zahl von Bits benutzt, die wir hier mit "e" bezeichnen.
Es wird dann ein Bias berechnet:
Bias:=(2 hoch (e-1))-1
Diese Zahl wird dann zum Exponenten hinzugezählt, das Ergebnis wird dann als "Charakteristik" bezeichnet, und diese wird dann vorzeichenlos anstelle des Exponenten gespeichert.
Der Exponent muss also, damit die Ausgangszahl gespeichert werden kann, zwischen einer (positiven) Obergrenze und einer (negativen) Untergrenze liegen.
Der Rest ist jetzt einfach zu erklären, wenn uns k Bits zur Speicherung der Mantisse zur Verfügung stehen, wird dieses Mantissenfeld mit den Nachkommastellen der Mantisse gefüllt, der Rest wird mit Nullen gefüllt. Doch was tun, wenn nicht genügend Bits zur Verfügung stehen, um alle Nachkommastellen zu speichern? Nun, dann tritt halt eine Rundungsungenauigkeit auf, Fließkommazahlen können also nicht immer die volle Genauigkeit speichern, was deren Einsatzmöglichkeiten begrenzt. Oftmals reicht die gegebene Genauigkeit jedoch aus.

Doch wo liegt der Vorteil dieser doch recht komplizierten Speicherung des Exponenten?
Ich möchte an dieser Stelle Prof. Dr. Hans Werner Lang zitieren:
Der IEEE 754 Floating-Point-Standard wurde auf Initiative von Intel Ende der 70er Jahre entwickelt, also noch bevor Floating-Point-Prozessoren gebaut wurden. Man wollte, bevor man anfängt, Floating-Point-Prozessoren zu bauen, ein einheitliches Format haben.

Und da hat man sich wohl gesagt, dass sowohl noch zu bauende Floating-Point-Prozessoren als auch Rechner ohne Floating-Point-Prozessoren es leichter haben, z.B. ein Array zu sortieren, was ja eine häufig vorkommende Operation ist, wenn die Floating-Point-Zahlen nur lexikographisch verglichen werden müssen, d.h. einfach so wie man Strings vergleicht. Man fängt bitweise vorne an, und die Zahl, die als erste eine 1 hat, während die andere an der entsprechenden Position eine 0 hat, ist die größere. Man braucht dabei nicht zu berücksichtigen, wo der Exponent aufhört und die Mantisse anfängt (was ja nicht an einer Wortgrenze ist).

Oder aber man führt mit den Wörtern, aus denen die Floating-Point-Zahlen bestehen, eine Integer-Subtraktion durch (wiederum ohne Berücksichtigung der Grenze zwischen Exponent und Mantisse).

Auch das ist leichter zu realisieren als eine Floating-Point-Subtraktion, die ja zunächst eine Exponenten-Anpassung und ein Schieben der einen Mantisse erfordert.

Nun noch ein paar Beispiele für die Anzahl der verwendeten Bits bei Fließkommazahlen.

Beispiel: "Short Real" (32 Bit) für Intel / Kompatible:
VZ: 1 Bit (reicht ja auch stets aus)
CH: 8 Bit
M: 23 Bit
Bias wäre hier: 127

Beispiel: "Long Real" (64 Bit) für Intel / Kompatible:
VZ: 1 Bit (reicht ja auch stets aus)
CH: 11 Bit
M: 52 Bit
Bias wäre hier: 1023

Wir sehen also, dass die Darstellung von Fließkommazahlen sehr viel aufwändiger als die Darstellung von ganzen Zahlen ist, weswegen moderne Prozessoren eine separate Gleitkommaeinheit (FPU, Floating Point Unit) besitzen, früher war zu diesem Zweck sogar ein zusätzlicher Prozessor ("Koprozessor") notwendig. Dieser kann zwar auch mit Software "nachgebaut", simuliert werden, dann benötigt jedoch jede einzelne Floating-Point-Berechnung recht viel Zeit.

Ganz zum Schluss möchte ich noch ein praxisnahes Beispiel bringen, bei dem die Genauigkeit der Mantisse nicht ausgereicht hat.

Manchen wird schon aufgefallen sein, das bei 3D-Spielen auf dem PC es vorkommen kann, dass zwei Objekte mit geringem Abstand zueinander bei einem 16-Bit-Z-Buffer (der intern floats nutzt) miteinander zu verschmelzen scheinen, was bei einem 32-Bit-Z-Buffer nicht geschieht. Dies ist genau die angesprochene Situation, zwei Zahlen, die ich in einer Fließkomma-Variable speichere, und die sich nur um einen geringen Wert voneinander unterscheiden, können zur selben Zahl werden, wenn die Bits für die Mantisse nicht ausgereicht haben, aus diesem Grunde sollte man als Programmierer ernsthafter Anwendungen bei der Nutzung von Fließkommazahlen stets vorsichtig sein.


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06243
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1144
Comments: 0