Scalaires
Les entiers
Faisons un rappel succinct du calcul scalaire dans les programmes. En dehors de toutes les représentations symboliques des scalaires, via les types simples, il y a deux grandes catégories d'objets scalaires dans les programmes: les entiers en virgule fixe, les réels en virgule flottante.
Les entiers
Le calcul entier est relativement simple. Les nombres sont en fait calculés dans une arithmétique modulo N = 2n où n est le nombre de bits des mots machines.
n N Exemple 16 65 536 = 6 × 104 Macintosh SE/30 32 4 294 967 296 = 4 × 109 Pentium 64 18 446 744 073 709 551 616 = 2 × 1019 Alpha
Figure i.1 : Bornes supérieures des nombres entiers
Ainsi, les processeurs de 1992 peuvent avoir une arithmétique précise sur quelques milliards de milliards, 100 fois plus rapide qu'une machine 16 bits! Il faut toutefois faire attention à la multiplication ou pire à la division qui a tendance sur les machines RISC (Reduced Instruction Set Computers) à prendre beaucoup plus de temps qu'une simple addition, typiquement 10 fois plus sur le processeur R3000 de Mips. Cette précision peut être particulièrement utile dans les calculs pour accéder aux fichiers. En effet, on a des disques de plus de 4 Giga Octets actuellement, et l'arithmétique 32 bits est insuffisante pour adresser leurs contenus.
Il faut pouvoir tout de même désigner des nombres négatifs. La notation couramment utilisée est celle du complément à 2. En notation binaire, le bit le plus significatif est le bit de signe. Au lieu de parler de l'arithmétique entre 0 et 2n - 1, les nombres sont pris entre -2n-1 et 2n-1 - 1. Soit, pour n=16, sur l'intervalle [-32768, 32767]. En Java, Integer.MAX\\_VALUE = 2n-1 - 1 est le plus grand entier positif et Integer.MIN\\_VALUE = - 2n-1 le plus petit entier négatif. En Caml, max\\_int = 2n-2 - 1 et min\\_int = -2n-2.
Une opération entre 2 nombres peut créer un débordement, c'est-à-dire atteindre les bornes de l'intervalle. Mais elle respecte les règles de l'arithmétique modulo N. Selon le langage de programmation et son implémentation sur une machine donnée, ce débordement est testé ou non. Ni Java, ni Caml ne font ces tests.
Il faut pouvoir tout de même désigner des nombres négatifs. La notation couramment utilisée est celle du complément à 2. En notation binaire, le bit le plus significatif est le bit de signe. Au lieu de parler de l'arithmétique entre 0 et 2n - 1, les nombres sont pris entre -2n-1 et 2n-1 - 1. Soit, pour n=16, sur l'intervalle [-32768, 32767]. En Java, Integer.MAX\\_VALUE = 2n-1 - 1 est le plus grand entier positif et Integer.MIN\\_VALUE = - 2n-1 le plus petit entier négatif. En Caml, max\\_int = 2n-2 - 1 et min\\_int = -2n-2.
Une opération entre 2 nombres peut créer un débordement, c'est-à-dire atteindre les bornes de l'intervalle. Mais elle respecte les règles de l'arithmétique modulo N. Selon le langage de programmation et son implémentation sur une machine donnée, ce débordement est testé ou non. Ni Java, ni Caml ne font ces tests.
Les nombres flottants
La notation flottante sert à représenter les nombres réels pour permettre d'obtenir des valeurs impossibles à obtenir en notation fixe. Un nombre flottant a une partie significative, la mantisse, et une partie exposant. Un nombre flottant tient souvent sur le même nombre de bits n qu'un nombre entier. En flottant, on décompose n = s + p + q en trois champs pour le signe, la mantisse et l'exposant, qui sont donnés par la machine. Ainsi tout nombre réel écrit ``signe decimal e exposant'' en Java ou Caml, vaut
Les nombres flottants sont une approximation des nombres réels, car leur partie significative f ne tient que sur un nombre p de bits fini. Par exemple, p = 23 en simple précision. Le nombre de bits pour l'exposant e est q = 8 en simple précision, ce qui fait que le nombre de bits total, avec le bit de signe, est bien 32.
Pour rendre portables des programmes utilisant les nombres flottants, une norme IEEE 754 (the Institute of Electrical and Electronics Engineers) a été définie. Non seulement elle décrit les bornes des nombres flottants, mais elle donne une convention pour représenter des valeurs spéciales: ± ¥, NaN (Not A Number) qui permettent de donner des valeurs à des divisions par zéro, ou à des racines carrées de nombres négatifs par exemple. Les valeurs spéciales permettent d'écrire des programmes de calcul de racines de fonctions éventuellement discontinues.
La norme IEEE est la suivante
signe decimal × 10 |
|
Les nombres flottants sont une approximation des nombres réels, car leur partie significative f ne tient que sur un nombre p de bits fini. Par exemple, p = 23 en simple précision. Le nombre de bits pour l'exposant e est q = 8 en simple précision, ce qui fait que le nombre de bits total, avec le bit de signe, est bien 32.
Pour rendre portables des programmes utilisant les nombres flottants, une norme IEEE 754 (the Institute of Electrical and Electronics Engineers) a été définie. Non seulement elle décrit les bornes des nombres flottants, mais elle donne une convention pour représenter des valeurs spéciales: ± ¥, NaN (Not A Number) qui permettent de donner des valeurs à des divisions par zéro, ou à des racines carrées de nombres négatifs par exemple. Les valeurs spéciales permettent d'écrire des programmes de calcul de racines de fonctions éventuellement discontinues.
La norme IEEE est la suivante
Exposant Mantisse Valeur e = emin - 1 f = 0 ± 0 e = emin - 1 f ¹ 0 0,f × 2emin emin £ e £ emax 1,f × 2e e = emax + 1 f = 0 ± ¥ e = emax + 1 f ¹ 0 NaN
Figure i.2 : Valeurs spéciales pour les flottants IEEE
et les formats en bits simple et double précision sont
Paramètre Simple Double p 23 52 q 8 11 emax +127 +1023 emin -126 -1022 Taille totale du mot 32 64
Figure i.3 : Formats des flottants IEEE
On en déduit donc que la valeur absolue de tout nombre flottant x vérifie en simple précision
10-45 » 2-150 £ |x| < 2128 » 3 × 1038
et en double précision
2 × 10-324 » 2-1075 £ |x| < 21024 » 10308
Par ailleurs, la précision d'un nombre flottant est 2-23 » 10-7 en simple précision et 2-52 » 2 × 10-16 en double précision. On perd donc 2 à 4 chiffres de précision par rapport aux opérations entières. Il faut comprendre aussi que les nombres flottants sont alignés avant toute addition ou soustraction, ce qui entraîne des pertes de précision. Par exemple, l'addition d'un très petit nombre à un grand nombre va laisser ce dernier inchangé. Il y a alors dépassement de capacité vers le bas (underflow). Un bon exercice est de montrer que la série harmonique converge en informatique flottante, ou que l'addition flottante n'est pas associative! Il y a aussi des débordements de capacité vers le haut (overflows). Ces derniers sont en général plus souvent testés que les dépassements vers le bas.
Enfin, pour être complet, la représentation machine des nombres flottants est légèrement différente en IEEE. En effet, on s'arrange pour que le nombre 0 puisse être représenté par le mot machine dont tous les bits sont 0, et on additionne la partie exposant du mot machine flottant de emin - 1, c'est-à-dire de 127 en simple précision, ou de 1023 en double précision.
10-45 » 2-150 £ |x| < 2128 » 3 × 1038
et en double précision
2 × 10-324 » 2-1075 £ |x| < 21024 » 10308
Par ailleurs, la précision d'un nombre flottant est 2-23 » 10-7 en simple précision et 2-52 » 2 × 10-16 en double précision. On perd donc 2 à 4 chiffres de précision par rapport aux opérations entières. Il faut comprendre aussi que les nombres flottants sont alignés avant toute addition ou soustraction, ce qui entraîne des pertes de précision. Par exemple, l'addition d'un très petit nombre à un grand nombre va laisser ce dernier inchangé. Il y a alors dépassement de capacité vers le bas (underflow). Un bon exercice est de montrer que la série harmonique converge en informatique flottante, ou que l'addition flottante n'est pas associative! Il y a aussi des débordements de capacité vers le haut (overflows). Ces derniers sont en général plus souvent testés que les dépassements vers le bas.
Enfin, pour être complet, la représentation machine des nombres flottants est légèrement différente en IEEE. En effet, on s'arrange pour que le nombre 0 puisse être représenté par le mot machine dont tous les bits sont 0, et on additionne la partie exposant du mot machine flottant de emin - 1, c'est-à-dire de 127 en simple précision, ou de 1023 en double précision.