Dans la plupart des langages de programmation, des nombres à virgule flottante sont représentés un peu comme de la notation scientifique: avec un exposant et la mantisse (aussi appelé le significande). Un très simple nombre, dire 9.2
, est en fait cette fraction:
5179139571476070 * 2 -49
Où l'exposant est - -49
et la mantisse est - 5179139571476070
. La raison pour laquelle il est impossible de représenter certains nombres décimaux de cette façon est que l'exposant et la mantisse doivent être des entiers. En d'autres termes, tous les flotteurs doit être un nombre entier multiplié par une puissance entière de 2.
9.2
peut-être tout simplement 92/10
, mais 10 ne peut pas être exprimé comme 2n si n est limitée à des valeurs entières.
Voir les Données
Tout d'abord, quelques fonctions pour voir les composants de 32 - et 64-bit float
. Brillant sur ces si vous ne s'intéressent qu'à la sortie (par exemple en 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)]
Il y a beaucoup de complexité inhérente à cette fonction, et que ce serait bien de la tangente à expliquer, mais si vous êtes intéressés, la ressource importante pour nous, c'est l' struct module.
Python float
est un 64 bits, nombre double précision. Dans d'autres langages tels que C, C++, Java et C#, double précision a un type distinct double
, ce qui est souvent mis en œuvre en version 64 bits.
Lorsque nous appeler cette fonction avec notre exemple, 9.2
, voici ce que nous obtenons:
>>> float_to_bin_parts(9.2)
['0', '10000000010', '0010011001100110011001100110011001100110011001100110']
L'interprétation des Données
Vous verrez que j'ai divisé la valeur de retour en trois volets. Ces composantes sont les suivantes:
- Signe
- Exposant
- Mantisse (également appelé Significande, ou une Fraction)
Signe
Le signe est stocké dans le premier composant que d'un seul bit. Il est facile à expliquer: - 0
signifie que le flotteur est un nombre positif; 1
signifie qu'il est négatif. Parce qu' 9.2
est positif, notre signe de la valeur est 0
.
Exposant
L'exposant est stocké dans le milieu de la composante de 11 bits. Dans notre cas, 0b10000000010
. En décimal, ce qui représente la valeur 1026
. Un caprice de cette composante est que vous devez soustraire un nombre égal à 2(nombre de bits) - 1 - 1 afin d'obtenir la valeur de l'exposant; dans notre cas, cela signifie que la soustraction 0b1111111111
(nombre décimal 1023
) afin d'obtenir la valeur de l'exposant, 0b00000000011
(nombre décimal 3).
Mantisse
La mantisse est stocké dans le troisième volet de 52 bits. Cependant, il y a une bizarrerie de ce composant. Pour comprendre cette bizarrerie, considérons un nombre en notation scientifique, comme ceci:
6.0221413x1023
La mantisse serait l' 6.0221413
. Rappelons que la mantisse en notation scientifique commence toujours avec un seul non-chiffre zéro. La même chose vaut pour les binaires, sauf que le binaire n'a que deux chiffres: 0
et 1
. De sorte que le binaire mantisse toujours commence avec 1
! Quand un flotteur est stockée, l' 1
à l'avant de la binaire mantisse est omis pour économiser de l'espace; nous avons à le replacer à l'avant de notre troisième élément pour obtenir le vrai mantisse:
1.0010011001100110011001100110011001100110011001100110
Cela implique plus qu'une simple addition, parce que les bits stockés dans notre troisième élément représentent les fractions de la partie de la mantisse, à droite de la radix point.
Lorsque vous traitez avec des nombres décimaux, nous "déplacer le point décimal" en multipliant ou en divisant par des puissances de 10. En binaire, nous pouvons faire la même chose en multipliant ou en divisant par des puissances de 2. Depuis notre troisième élément a 52 bits, on divise par 252 pour le déplacer 52 places vers la droite:
0.0010011001100110011001100110011001100110011001100110
En notation décimale, c'est la même chose que diviser 675539944105574
par 4503599627370496
pour obtenir de l' 0.1499999999999999
. (C'est un exemple d'un rapport qui peut être exprimé exactement en binaire, mais seulement environ en décimal; pour plus de détails, voir: 675539944105574 / 4503599627370496.)
Maintenant que nous avons transformé le troisième composant dans un nombre fractionnaire, l'ajout d' 1
donne le vrai de la mantisse.
Récapitulatif sur les Composants
- Signe (première composante):
0
pour le positif, 1
pour les négatifs
- L'exposant (composant intermédiaire): Soustraire 2(nombre de bits) - 1 - 1 afin d'obtenir la valeur de l'exposant
- Mantisse (dernier volet): Diviser par 2(nombre de bits) et ajouter
1
afin d'obtenir la valeur de la mantisse
Le calcul du Nombre
Mettre ensemble des trois parties, nous nous sommes donné ce nombre binaire:
1.0010011001100110011001100110011001100110011001100110 x 1011
Que nous pouvons ensuite convertir de binaire en décimal:
1.1499999999999999 x 23 (inexact!)
Et de se multiplier pour révéler la dernière représentation du nombre, nous avons commencé avec (9.2
) après avoir été stockée en tant que valeur en virgule flottante:
9.1999999999999993
Représentant qu'une Fraction
9.2
Maintenant que nous avons établi le nombre, il est possible de le reconstruire en une fraction simple:
1.0010011001100110011001100110011001100110011001100110 x 1011
Maj de la mantisse d'un nombre entier:
10010011001100110011001100110011001100110011001100110 x 1011-110100
Convertir en décimal:
5179139571476070 x 23-52
Soustraire l'exposant:
5179139571476070 x 2-49
Tourner à exposant négatif de la division:
5179139571476070 / 249
Multiplier exposant:
5179139571476070 / 562949953421312
Ce qui équivaut à:
9.1999999999999993
9.5
>>> float_to_bin_parts(9.5)
['0', '10000000010', '0011000000000000000000000000000000000000000000000000']
Vous pouvez déjà voir la mantisse n'est qu'à 4 chiffres suivis par tout un tas de zéros. Mais nous allons aller aux rythmes de la musique.
Assembler le binaire notation scientifique:
1.0011 x 1011
Déplacer le point décimal:
10011 x 1011-100
Soustraire l'exposant:
10011 x 10-1
Binaire à décimal:
19 x 2-1
L'exposant négatif de la division:
19 / 21
Multiplier exposant:
19 / 2
Est égal à:
9.5
Lectures complémentaires