Ce qui m'intéresse c'est la vérité mathématique et pas la vérité IEEE.
La norme IEEE-754 respecte très bien la vérité mathématique, mais j'y reviendrais après.
Pour contextualiser un peu, j'en suis venu récemment à python (puis ce "problème") parce que Python va être enseigné de plus en plus en lycée. Bon, bah c'est simple : "Madame/Monsieur, votre truc marche pas, il ne sait pas calculer (calculs habituels décimaux) aussi bien que ma calculatrice"
Bien au contraire ! C'est un très bon prétexte pour leur faire travailler leurs mathématiques. :-)
Je m'explique en illustrant par une approche possible (je ne suis pas là pour produire du matériel d'enseignement) en partant de ce que les élèves maîtrisent bien : la base 10 (et c'est cela qui choque dans l'exemple du journal).
Là je ne fais que charger de quoi travailler avec des nombres flottants en base 10 : des décimaux, en somme; et je fixe une précision assez basse pour avoir de petits nombres.
Hop, on définit les nombres 1, 2, 3 et on fait quelques calculs avec. On voit un peu à quoi correspondait le ctx.prec = 3 de tout à l'heure (pour l'instant, c'est le chiffre de nombre après la virgule). Le résultat de la première opération doit être familière à tout lycéen : il sait que si l'on divise 1 par 3, il aura une infinité de 3 après la virgule et là il n'en garde que trois.
Pour la seconde opération, il sait très bien que 2 * 333 = 666 d'où 2 * 0.333 = 0.666. La fraction a était approximée avant la multiplication, mais ensuite le calcul de celle-ci est on ne peut plus conforme à la « vérité mathématique » (qui te tient tant à cœur). En revanche si l'on pratique directement la division de 2 par 3, puis que l'on approxime au plus proche en ne conservant que trois chiffres après la virgule, on obtient un autre résultat, à savoir 0.667.
On peut continuer et montrer quelques « étrangetés » (qui n'en seront sans doute pas pour des lycéens) du calcul selon les règles strictes de l'arithmétique mais avec des arrondis.
Et là c'est tout à fait compréhensible. Selon les règles strictes de l'arithmétique, on a bien 333 +たす 333 +たす 333 =わ 3 * 333 = 999. Et pour le dernier, on a bien 333 + 667 = 1000 ou dans notre cas 0.333 + 0.667 = 1.000, mais comme la précision est de 3 il n'affiche que 1.00. En fait la précision c'est la taille de la mantisse, c'est à dire que le nombre est vu comme 100 \times 10^{-2}, là où un /trois est vu comme 333 \times 10^{-3}.
Il me semble bien que tout ce qui précède est largement accessible à des lycéens. Il suffit ensuite de développer la chose en leur expliquant que le même genre de phénomène se produit si l'on prend une base 2 au lieu d'une base 10, et que c'est dans cette base que travaille python par défaut.
Les deux « erreurs » de calcul relèvent des mêmes principes mathématiques mais dans deux bases distinctes.
Pour revenir, et conclure, sur cette histoire de standard IEEE. Le calcul flottant en base 2 a été normalisé en 1985 sous le nom de standard IEEE-7554. En 2008, y a été ajouté une normalisation de la base 10 (utilisée ici par Python), et j'avais donné plus haut le lien vers la page de l'ingénieur IBM qui s'en est occupé. Python datant de 1990, les matériels ayant implanté le standard de 1985 dans leur FPU, on peut comprendre pourquoi, par défaut, ce langage utilise la base 2 et non la base 10.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Commentaire de soutien ;-)
Posté par kantien . En réponse au journal [Humour] vers un monde différent. Évalué à 3.
La norme IEEE-754 respecte très bien la vérité mathématique, mais j'y reviendrais après.
Bien au contraire ! C'est un très bon prétexte pour leur faire travailler leurs mathématiques. :-)
Je m'explique en illustrant par une approche possible (je ne suis pas là pour produire du matériel d'enseignement) en partant de ce que les élèves maîtrisent bien : la base
10(et c'est cela qui choque dans l'exemple du journal).Là je ne fais que charger de quoi travailler avec des nombres flottants en base
10: des décimaux, en somme; et je fixe une précision assez basse pour avoir de petits nombres.Hop, on définit les nombres
1, 2, 3et on fait quelques calculs avec. On voit un peu à quoi correspondait lectx.prec = 3de tout à l'heure (pour l'instant, c'est le chiffre de nombre après la virgule). Le résultat de la première opération doit être familière à tout lycéen : il sait que si l'on divise1par3, il aura une infinité de3après la virgule et là il n'en garde que trois.Pour la seconde opération, il sait très bien que
2 * 333 = 666d'où2 * 0.333 = 0.666. La fraction a était approximée avant la multiplication, mais ensuite le calcul de celle-ci est on ne peut plus conforme à la « vérité mathématique » (qui te tient tant à cœur). En revanche si l'on pratique directement la division de2par3, puis que l'on approxime au plus proche en ne conservant que trois chiffres après la virgule, on obtient un autre résultat, à savoir0.667.On peut continuer et montrer quelques « étrangetés » (qui n'en seront sans doute pas pour des lycéens) du calcul selon les règles strictes de l'arithmétique mais avec des arrondis.
Et là c'est tout à fait compréhensible. Selon les règles strictes de l'arithmétique, on a bien
333 +たす 333 +たす 333 =わ 3 * 333 = 999. Et pour le dernier, on a bien333 + 667 = 1000ou dans notre cas0.333 + 0.667 = 1.000, mais comme la précision est de3il n'affiche que1.00. En fait la précision c'est la taille de la mantisse, c'est à dire que le nombre est vu comme 100 \times 10^{-2}, là oùun /troisest vu comme 333 \times 10^{-3}.Illustration du changement de précision :
Il me semble bien que tout ce qui précède est largement accessible à des lycéens. Il suffit ensuite de développer la chose en leur expliquant que le même genre de phénomène se produit si l'on prend une base
2au lieu d'une base10, et que c'est dans cette base que travaille python par défaut.Les deux « erreurs » de calcul relèvent des mêmes principes mathématiques mais dans deux bases distinctes.
Pour revenir, et conclure, sur cette histoire de standard IEEE. Le calcul flottant en base
2a été normalisé en 1985 sous le nom de standard IEEE-7554. En 2008, y a été ajouté une normalisation de la base 10 (utilisée ici par Python), et j'avais donné plus haut le lien vers la page de l'ingénieur IBM qui s'en est occupé. Python datant de 1990, les matériels ayant implanté le standard de 1985 dans leur FPU, on peut comprendre pourquoi, par défaut, ce langage utilise la base2et non la base10.Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.