ieee754-pourquoi_les_calculs_informatiques_sont_faux
DESCRIPTION
La norme IEEE754 définit la représentation en mémoire et les règles de calcul pour les nombres flottants. IEEE754 est utilisée par la plupart des langages informatiques. Cette norme induit des effets de bord qui provoquent des résultats erronés lors de certaines opérations mathématiques.TRANSCRIPT
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
IEEE754Manipulation des nombres flottants :
exemples avec Javascript
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Human talker
Mickaël Ruau :• formateur pour le titre développeur logiciel (niveau III)
à l’AFPA d’Angers• consultant en gestion du cycle de vie du logiciel
(forges logicielles)
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Objectif
A la fin de cette présentation, vous maîtriserez la manipulation des nombres à virgule flottante.
- Vous comprendrez les effets de bords liés aux arrondis de la norme IEEE754- Vous serez capables d'améliorer l'exactitude des calculs sur les nombres à virgule flottante.
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Disclaimer
Le but est de sensibiliser aux problèmes liés aux calculs informatiques, notamment en matière financière (comptabilité, paie, ecommerce...).
Je ne suis pas mathématicien.Je n’ai pas écrit la norme IEEE754, je ne la connais pas par coeur!
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Références
http://blog.oaxoa.com/2008/03/22/weird-math-aka-ieee-754-double-precision-floating-point-number-sukcs/
http://grouper.ieee.org/groups/754/faq.htmlhttp://www.haypocalc.com/wiki/Standards_IEEE_754_et_854
http://floating-point-gui.de/languages/javascript/http://www.ecmascript.org/Standard ECMA-262 3rd Edition - December 1999ECMA-262 5.1 Edition - June 2011
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
La minute nécessaire
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Etonnant, non?!
console.log(0.1+0.2); //0.30000000000000004
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Etonnant, non?! (suite)
console.log(0.1*0.2); //0.020000000000000004
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Etonnant, non?! (re-suite)
console.log(0.11/0.10); //1.0999999999999999
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Etonnant, non?! (fin)
console.log(0.3 - 0.2 ); //0.09999999999999998
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Explication
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
La cancellation
http://fr.wikipedia.org/wiki/Virgule_flottante#Pr.C3.A9cautions_d.27emploi
Les calculs en virgule flottante (...) présentent divers
désagréments, notamment leur précision limitée, qui se
traduit par des arrondis. (...)
Pour cette raison, les travaux de comptabilité ne sont pas
effectués en virgule flottante, car tout doit tomber juste au
centième près. En particulier, la soustraction de deux
nombres très proches provoque une grande perte de
précision relative : on parle de « cancellation ».
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Pourquoi 0.1 n’est pas 0.1?
http://www.haypocalc.com/wiki/Standards_IEEE_754_et_854
En gros, on stocke les nombres sous la forme :
(signe, mantisse, exposant)
ce qui donne x = signe * mantisse * (2 ^ exposant).
Le signe vaut +1 ou -1, la mantisse est un nombre réel
tel que 1.0 <= mantisse < 2.0,
et l'exposant est une valeur entière.
Bien sûr, l'ensemble est codé en binaire !
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Exemples de format de stockage
Le nombre 3 est stocké (+1, 1.5, 1) :
3 = (+1) * 1.5 * (2 ^ 1).
Le nombre 10 est stocké (+1, 1.25, 3) :
10 = (+1) * 1.25 * 2^3.
Le nombre 2 est stocké (+1, 1, 1), c'est-à-dire : 2 = (+1) * 1 * (2 ^ 1).
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Personne ne coule?Décomposons un flottant
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Le signe
• (+1) si le nombre est positif
• (-1) si le nombre est négatif
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
La mantisse
• Si le nombre est supérieur à 1.5, il faut le diviser
successivement par deux, jusqu'à ce que sa valeur soit
inférieure ou égale à 1.5 (l'exposant sera le nombre de
division)
• Si le nombre est inférieur à 1, il faut le multiplier
successivement par deux, jusqu'à ce que sa valeur soit
supérieure ou égale à 1 (l'exposant sera le nombre
opposé de divisions).
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Exemple : x = -10
• Le signe est égal à -1, car le nombre est négatif.
• On prend la valeur absolue : x=10.
Comme sa valeur est supérieur à 1, on divise par 2 :
x=5, exposant=1.
On continue : x=2.5 et exposant=2,
x=1.25 et exposant=3 : STOP !
Donc finalement, x=(-1) * 1.25 * (2^3).
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Quelqu’un peut le faire pour moi?
http://babbage.cs.qc.cuny.edu/IEEE-754/This page lets you examine the relationships among binary and decimal numbers and three number formats described by the IEEE-754-2008 floating-point standard.
You can enter a numeric value in any one of five formats, and see all five corresponding values :Decimal, Normalized Binary, Binary32 (single precision), Binary64 (double precision), and Binary128 (quad precision), along with analyses of the binary structure of the floating-point formats.
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
... Encore?D'autres exemples...
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Trop c'est trop!
var n1 = 123456789012345672;console.log(n1); // affiche 123456789012345660
var n2 = 123456789012345673;console.log(n2); // affiche 123456789012345680
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Mini, mini, mini
console.log(1.00000000000000009);// affiche 1
console.log(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001); // affiche 1e-323
console.log(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001); // affiche 0
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
" Il faut une infinie patience pour attendre toujours ce qui n'arrive jamais. " (PIERRE DAC)
console.log(99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); //affiche 1e+308
console.log(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); //affiche Infinity
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
" Il faut toujours prendre le maximum de risques avec le maximum de précautions. " Rudyard Kipling
console.log(3+999999999999999);//affiche 1000000000000002console.log(2+999999999999999);//affiche 1000000000000001
console.log(3+9999999999999999);//affiche 1000000000000004console.log(2+9999999999999999);//affiche 1000000000000002
console.log(3+99999999999999999);//affiche 100000000000000000console.log(2+99999999999999999);//affiche 100000000000000000
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Explication
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
IEEE 754 overflow
http://fr.wikipedia.org/wiki/Virgule_flottante
Les calculs en virgule flottante sont pratiques, mais présentent divers désagréments, notamment :
● une plage d'exposants limitée, pouvant donner lieux à ○ des « overflows » (lorsque le résultat d'une
opération est plus grand que la plus grande valeur représentable)
○ et à des « underflows » (lorsqu'un résultat est plus petit, en valeur absolue, que le plus petit flottant normalisé positif),
○ puis à des résultats n'ayant plus aucun sens.
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Quelles solutions?
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Number() = IEEE 64 bit
JavaScript is dynamically typed and will often convert
implicitly between strings and floating-point numbers (which
are IEEE 64 bit values). To force a variable to floating-
point, use the global parseFloat() function.
var num = parseFloat("3.5");
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
https://github.com/dtrebbien/BigDecimal.js
Decimal Types
The best decimal type for JavaScript seems to be a port of Java’s BigDecimal
class, which also supports rounding modes:
var a = new BigDecimal("0.01");var b = new BigDecimal("0.02");var c = a.add(b); // 0.03var d = c.setScale(1, BigDecimal.prototype.ROUND_HALF_UP);
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
https://github.com/dtrebbien/BigDecimal.js
How to Round
var num = 5.123456;num.toPrecision(1) //returns 5 as stringnum.toPrecision(2) //returns 5.1 as stringnum.toPrecision(4) //returns 5.123 as string
Using a specific rounding mode:
new BigDecimal("1.25").setScale(1, BigDecimal.prototype.ROUND_HALF_UP);
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
BilanObjectif atteint?
Sh
ake
r tec h
no
logie
s J ava
script-I E
EE
75
4 ve
rsion
1.0
Merci de votre attention.