In den meisten Programmiersprachen werden Gleitkommazahlen ähnlich wie in der wissenschaftlichen Notation dargestellt : mit einem Exponenten und einer Mantisse (auch als Signifikand bezeichnet). Eine sehr einfache Zahl 9.2
ist beispielsweise dieser Bruchteil:
5179139571476070 * 2 -49
Wo der Exponent ist -49
und die Mantisse ist 5179139571476070
. Der Grund, warum es unmöglich ist, einige Dezimalzahlen auf diese Weise darzustellen, ist, dass sowohl der Exponent als auch die Mantisse ganze Zahlen sein müssen. Mit anderen Worten, alle Floats müssen eine ganze Zahl multipliziert mit einer ganzzahligen Potenz von 2 sein .
9.2
kann einfach sein 92/10
, aber 10 kann nicht als 2 n ausgedrückt werden, wenn n auf ganzzahlige Werte beschränkt ist.
Daten anzeigen
Zunächst einige Funktionen, um die Komponenten zu sehen , aus denen ein 32- und 64-Bit besteht float
. Beschönigen Sie diese, wenn Sie sich nur für die Ausgabe interessieren (Beispiel in Python):
def float_to_bin_parts(number, bits=64):
if bits == 32: # single precision
int_pack = 'I'
float_pack = 'f'
exponent_bits = 8
mantissa_bits = 23
exponent_bias = 127
elif bits == 64: # double precision. all python floats are this
int_pack = 'Q'
float_pack = 'd'
exponent_bits = 11
mantissa_bits = 52
exponent_bias = 1023
else:
raise ValueError, 'bits argument must be 32 or 64'
bin_iter = iter(bin(struct.unpack(int_pack, struct.pack(float_pack, number))[0])[2:].rjust(bits, '0'))
return [''.join(islice(bin_iter, x)) for x in (1, exponent_bits, mantissa_bits)]
Hinter dieser Funktion steckt eine Menge Komplexität, und es wäre ziemlich tangential zu erklären, aber wenn Sie interessiert sind, ist die Struktur die wichtige Ressource für unsere Zwecke .
Python float
ist eine 64-Bit-Zahl mit doppelter Genauigkeit. In anderen Sprachen wie C, C ++, Java und C # hat die doppelte Genauigkeit einen separaten Typ double
, der häufig als 64-Bit implementiert wird.
Wenn wir diese Funktion mit unserem Beispiel aufrufen, erhalten 9.2
wir Folgendes:
>>> float_to_bin_parts(9.2)
['0', '10000000010', '0010011001100110011001100110011001100110011001100110']
Daten interpretieren
Sie werden sehen, dass ich den Rückgabewert in drei Komponenten aufgeteilt habe. Diese Komponenten sind:
- Zeichen
- Exponent
- Mantisse (auch Signifikand oder Bruch genannt)
Zeichen
Das Vorzeichen wird in der ersten Komponente als einzelnes Bit gespeichert. Es ist leicht zu erklären: 0
bedeutet, dass der Float eine positive Zahl ist; 1
bedeutet, dass es negativ ist. Weil 9.2
positiv ist, ist unser Vorzeichenwert0
.
Exponent
Der Exponent wird in der mittleren Komponente als 11 Bit gespeichert. In unserem Fall 0b10000000010
. In Dezimalzahlen entspricht dies dem Wert 1026
. Eine Besonderheit dieser Komponente ist, dass Sie eine Zahl von 2 ( Anzahl der Bits) - 1 - 1 subtrahieren müssen , um den wahren Exponenten zu erhalten. In unserem Fall bedeutet dies Subtrahieren 0b1111111111
(Dezimalzahl 1023
), um den wahren Exponenten 0b00000000011
(Dezimalzahl 3) zu erhalten.
Mantisse
Die Mantisse ist in der dritten Komponente als 52 Bit gespeichert. Diese Komponente hat jedoch auch eine Besonderheit. Um diese Eigenart zu verstehen, betrachten Sie eine Zahl in wissenschaftlicher Notation wie folgt:
6.0221413x10 23
Die Mantisse wäre die 6.0221413
. Denken Sie daran, dass die Mantisse in wissenschaftlicher Notation immer mit einer einzelnen Ziffer ungleich Null beginnt. Das gleiche gilt für Binär, außer dass Binär nur zwei Ziffern hat: 0
und 1
. Die binäre Mantisse beginnt also immer mit 1
! Wenn ein Float gespeichert ist, wird die 1
Vorderseite der binären Mantisse weggelassen, um Platz zu sparen. Wir müssen es wieder vor unser drittes Element setzen, um die wahre Mantisse zu erhalten:
1.0010011001100110011001100110011001100110011001100110
Dies beinhaltet mehr als nur eine einfache Addition, da die in unserer dritten Komponente gespeicherten Bits tatsächlich den Bruchteil der Mantisse rechts vom Radixpunkt darstellen .
Beim Umgang mit Dezimalzahlen "verschieben wir den Dezimalpunkt" durch Multiplizieren oder Dividieren mit Potenzen von 10. In Binärzahlen können wir dasselbe tun, indem wir mit Potenzen von 2 multiplizieren oder dividieren. Da unser drittes Element 52 Bits hat, teilen wir es um 2 52 , um es 52 Stellen nach rechts zu bewegen:
0,0010011001100110011001100110011001100110011001100110
In Dezimalschreibweise entspricht dies dem Teilen 675539944105574
durch 4503599627370496
, um zu erhalten 0.1499999999999999
. (Dies ist ein Beispiel für ein Verhältnis, das genau in Binärform, aber nur ungefähr in Dezimalzahl ausgedrückt werden kann . Weitere Informationen finden Sie unter: 675539944105574/4503599627370496 .)
Nachdem wir die dritte Komponente in eine Bruchzahl umgewandelt haben, 1
ergibt das Hinzufügen die wahre Mantisse.
Komponenten neu zusammenfassen
- Vorzeichen (erste Komponente):
0
für positiv, 1
für negativ
- Exponent (mittlere Komponente): Subtrahieren Sie 2 (Anzahl der Bits) - 1 - 1 , um den wahren Exponenten zu erhalten
- Mantisse (letzte Komponente): Teilen Sie durch 2 (Anzahl der Bits) und addieren Sie
1
, um die wahre Mantisse zu erhalten
Berechnung der Anzahl
Wenn wir alle drei Teile zusammenfügen, erhalten wir diese Binärzahl:
1.0010011001100110011001100110011001100110011001100110 x 10 11
Was wir dann von binär nach dezimal konvertieren können:
1.1499999999999999 x 2 3 (ungenau!)
Und multiplizieren Sie, um die endgültige Darstellung der Zahl anzuzeigen, mit der wir begonnen haben ( 9.2
), nachdem sie als Gleitkommawert gespeichert wurde:
9.1999999999999993
Darstellen als Bruch
9.2
Nachdem wir die Zahl erstellt haben, ist es möglich, sie in einen einfachen Bruch zu rekonstruieren:
1.0010011001100110011001100110011001100110011001100110 x 10 11
Verschieben Sie die Mantisse auf eine ganze Zahl:
10010011001100110011001100110011001100110011001100110 x 10 11-110100
In Dezimalzahl konvertieren:
5179139571476070 x 2 3-52
Subtrahieren Sie den Exponenten:
5179139571476070 x 2 -49
Negativen Exponenten in Division umwandeln:
5179139571476070/2 49
Exponent multiplizieren:
5179139571476070/562949953421312
Was gleich ist:
9.1999999999999993
9.5
>>> float_to_bin_parts(9.5)
['0', '10000000010', '0011000000000000000000000000000000000000000000000000']
Sie können bereits sehen, dass die Mantisse nur 4-stellig ist, gefolgt von einer ganzen Reihe von Nullen. Aber lassen Sie uns durch die Schritte gehen.
Stellen Sie die binäre wissenschaftliche Notation zusammen:
1,0011 x 10 11
Verschieben Sie den Dezimalpunkt:
10011 x 10 11-100
Subtrahieren Sie den Exponenten:
10011 x 10 & supmin; ¹
Binär bis dezimal:
19 x 2 -1
Negativer Exponent zur Teilung:
19/2 1
Exponent multiplizieren:
19/2
Gleich:
9.5
Weiterführende Literatur