(Remarque: je vais ajouter «b» pour indiquer les nombres binaires ici. Tous les autres nombres sont donnés en décimal)
Une façon de penser les choses est en termes de quelque chose comme la notation scientifique. Nous sommes habitués à voir des nombres exprimés en notation scientifique comme 6.022141 * 10 ^ 23. Les nombres à virgule flottante sont stockés en interne en utilisant un format similaire - mantisse et exposant, mais en utilisant des puissances de deux au lieu de dix.
Votre 61.0 pourrait être réécrit en 1.90625 * 2 ^ 5, ou 1.11101b * 2 ^ 101b avec la mantisse et les exposants. Pour multiplier cela par dix et (déplacer le séparateur décimal), nous pouvons faire:
(1,90625 * 2 ^ 5) * (1,25 * 2 ^ 3) = (2,3828125 * 2 ^ 8) = (1,19140625 * 2 ^ 9)
ou avec la mantisse et les exposants en binaire:
(1.11101b * 2 ^ 101b) * (1.01b * 2 ^ 11b) = (10.0110001b * 2 ^ 1000b) = (1.00110001b * 2 ^ 1001b)
Notez ce que nous avons fait là pour multiplier les nombres. Nous avons multiplié les mantisses et ajouté les exposants. Puis, comme la mantisse s'est terminée au-delà de deux, nous avons normalisé le résultat en frappant l'exposant. C'est comme lorsque nous ajustons l'exposant après avoir effectué une opération sur des nombres en notation scientifique décimale. Dans chaque cas, les valeurs avec lesquelles nous avons travaillé avaient une représentation finie en binaire, et donc les valeurs produites par les opérations de multiplication et d'addition de base produisaient également des valeurs avec une représentation finie.
Maintenant, considérons comment nous diviserions 61 par 10. Nous commencerions par diviser les mantisses, 1,90625 et 1,25. En décimal, cela donne 1,525, un joli nombre court. Mais qu'est-ce que c'est si nous le convertissons en binaire? Nous le ferons de la manière habituelle - en soustrayant la plus grande puissance de deux dans la mesure du possible, tout comme la conversion de décimales entières en binaires, mais nous utiliserons des puissances négatives de deux:
1,525 - 1 * 2 ^ 0 -> 1
0,525 - 1 * 2 ^ -1 -> 1
0,025 - 0 * 2 ^ -2 -> 0
0,025 - 0 * 2 ^ -3 -> 0
0,025 - 0 * 2 ^ -4 -> 0
0,025 - 0 * 2 ^ -5 -> 0
0,025 - 1 * 2 ^ -6 -> 1
0,009375 - 1 * 2 ^ -7 -> 1
0,0015625 - 0 * 2 ^ -8 -> 0
0,0015625 - 0 * 2 ^ -9 -> 0
0,0015625 - 1 * 2 ^ -10 -> 1
0,0005859375 - 1 * 2 ^ -11 -> 1
0,00009765625 ...
Euh oh. Maintenant, nous avons des ennuis. Il s'avère que 1.90625 / 1.25 = 1.525, est une fraction répétitive lorsqu'elle est exprimée en binaire: 1.11101b / 1.01b = 1.10000110011 ... b Nos machines ont seulement tellement de bits pour contenir cette mantisse et donc elles vont juste arrondir la fraction et assumer des zéros au-delà d'un certain point. L'erreur que vous voyez lorsque vous divisez 61 par 10 est la différence entre:
1.100001100110011001100110011001100110011 ... b * 2 ^ 10b
et, par exemple:
1.100001100110011001100110b * 2 ^ 10b
C'est cet arrondi de la mantisse qui conduit à la perte de précision que nous associons aux valeurs à virgule flottante. Même lorsque la mantisse peut être exprimée exactement (par exemple, en ajoutant simplement deux nombres), nous pouvons toujours obtenir une perte numérique si la mantisse a besoin de trop de chiffres pour tenir après la normalisation de l'exposant.
En fait, nous faisons ce genre de chose tout le temps lorsque nous arrondissons des nombres décimaux à une taille gérable et que nous donnons simplement les premiers chiffres de celui-ci. Parce que nous exprimons le résultat en décimal, cela semble naturel. Mais si nous arrondissions une décimale, puis la convertissons en une base différente, cela semblerait aussi laid que les décimales que nous obtenons en raison de l'arrondi en virgule flottante.