Hello,
j'ai un truc bizarre, reproductible sur plus de 4 environements:
Soit le script
http://www.lzi.ch/plop.phps(...)
Résultat:
http://www.lzi.ch/plop.php(...)
Pourquoi 19.89 et pas 19.90? Quelqu'un a déjà vu ça? Non, c'est pas des pentioumes buggés, enfin: pas officiellement :)
# :)
Posté par Marc (site web personnel) . Évalué à 3.
# Histoire de codage
Posté par med . Évalué à 1.
# 100.00
Posté par Julien Duponchelle (site web personnel) . Évalué à 1.
[^] # Re: 100.00
Posté par Lol Zimmerli (site web personnel, Mastodon) . Évalué à 1.
http://www.lzi.ch/plop.php(...) http://www.lzi.ch/plop.phps(...)
Et même avec 15.90, c'est ok. Qu'est-ce que le type qui a écrit ça a contre 1990?? :*)
La gelée de coings est une chose à ne pas avaler de travers.
[^] # Re: 100.00
Posté par xalbat . Évalué à 1.
Voila ce que l'on obtient :
-->a=19.90
a =
19.9
-->a*100
ans =
1990.
-->int(a*100)
ans =
1989.
-->a2=15.9
a2 =
15.9
-->int(a2*100)
ans =
1590.
-->b=a*100
b =
1990.
-->int(b)
ans =
1989.
-->int(1990)
ans =
1990.
-->round(b)
ans =
1990.
round(x) : arrondit les éléments de x aux entiers les plus proches.
int(X) : renvoie une matrice d'entiers dont les éléments sont les arrondis vers zéro des éléments de x.
-->int(b*10000)
ans =
19899999.
-->int(b*10000000)
ans =
1.990D+10
Voila ce qu'il en est dans Scilab : pareil en clair
[^] # Re: 100.00
Posté par Lol Zimmerli (site web personnel, Mastodon) . Évalué à 1.
Python 2.3.5 (#2, Jun 19 2005, 13:28:00)
>>> 19.90 * 100
1989.9999999999998
>>> 15.90 * 100
1590.0
ça m'scie l'caramel :-/
La gelée de coings est une chose à ne pas avaler de travers.
[^] # Re: 100.00
Posté par Vincent Behar . Évalué à 3.
irb(main):001:0> 15.90 * 100
=> 1590.0
irb(main):002:0> 19.90 * 100
=> 1990.0
change de caramel ça ira mieux ;-)
[^] # Re: 100.00
Posté par Amand Tihon (site web personnel) . Évalué à 1.
>>> print 19.90 * 100
1990.0
:)
# BCMath
Posté par tito (site web personnel) . Évalué à 1.
http://fr.php.net/manual/fr/ref.bc.php(...)
# explication
Posté par Vincent Behar . Évalué à 1.
http://blog.leetsoft.com/articles/2005/09/27/wtf(...)
# Tout à fait
Posté par spotty . Évalué à 2.
Pour contourner ce problème, si on a besoin de précision (et donc éviter les problèmes d'arrondi) il faut utiliser http://lu.php.net/manual/fr/ref.bc.php(...) Binary Calculator.
Maintenant à toi de voir si ton projet a vraiment besoin de cette précision ou si l'arrondi est acceptable
[^] # Re: Tout à fait
Posté par Cali_Mero . Évalué à 3.
# Codage des floats
Posté par Damien Metzler . Évalué à 4.
0b => 0d
1b=> 1d
10b => 2d
etc....
et un nombre se décompose sur les puissances de 2
18 = 0*1 + 1*2^1 + 0*2^2 + 0*2^3 + 1*2^4 = 10010b
Quand tu code un flottant, la partie après la virgule est aussi codée en binaire en décomposant par puissance négative de 2
a*1/2^1 + b*1/2^2 +c*1/2^3 + ... + x*1/2^n
Un nombre comme 1/3 a un nombre de virgule infini. Donc on ne pourra jamais trouver un "décomposition en série de 1/2^n" finie égale à 1/3. Un float est stocké sur un nombre fini de bits et donc s'approchera plus ou moins bien de ton 1/3 mais n'y arrivera jamais exactement.
Conclusion quand tu réaffiche ton nombre, il affiche la valeur stockée.
Ex : 0.8126 si on a que 4bits de précisions
0.826 = 1/2 + 1/4 + 0/8 +1/16 (+1/10000)
La partie 1/10000 n'est pas codable avec notre système, quand on réaffichera notre nombre stocké, on aura 0.825 et non 0.826
[^] # Re: Codage des floats
Posté par xalbat . Évalué à 1.
19.90d = 19d + 0.90d
19d = 16 + 2 + 1 = 10011b
0.90d = 1/2 + 1/4 + 1/8 + 1/64 + 1/128 + 1/1024 + 1/2048 ...
= 1/2^1 + 1/2^2 + 1/2^3 + 1/2^6 + 1/2^7 + 1/2^10 + 1/2^11 + 1/2^14 + 1/2^15 + etc . etc.
= 111001100110011...
Donc comme dans ton exemple 0.90 n'est pas codable.
Maintenant, j'ai une question : qu'est-ce qui rend 15.90d codable et 19.90 non codable ? Parce si on regarde bien, seul 19.90 pose problème ci-dessus.
J'au eu beau chercher dans Wikipedia, Google, rien de probant
[^] # Re: Codage des floats
Posté par Éric (site web personnel) . Évalué à 4.
Ce que tu fais c'est retrancher la partie entière et remarquer que la partie décimale est identique. Et là tu te dis que la précision devrait être la même.
Ton erreur c'est que le soft ne sépare pas la partie entière et la partie décimale. Lui sépare un nombre et une puissance : X * 10^Y, il stocke X et Y.
Bref, ce n'est pas 15 + 0.90 et 19 + 0.90 qu'il faut comparer mais 0.1590 * 10^2 et 0.1990 * 10^2. La bonne question c'est donc : 0.1590 et 0.1990 sont exprimables en puissance de deux ?
Note : je parle de mémoire de mes anciens cours, je peux me tromper sur les détails, mais le principe est là. Tu ne peux pas te contenter de dire que vu que la partie décimale est la même si l'un est stockable l'autre l'est.
[^] # Re: Codage des floats
Posté par Black Fox . Évalué à 2.
Ce qui en tout fait 3 cas, dont un ne donne pas ce à qui on s'attends quant on cast en int, la conclusion est simple : faire un cast d'un nombre IEEE-754 vers un int c'est chercher les emmerdes.
# moi aussi
Posté par Cyber Kobold (site web personnel) . Évalué à 2.
j'ai fait un script pour la notation scientifique (cours de seconde math/physique)
http://kobold.myftp.org/math/ecriture_science.php(...)
Le script génère un nombre aléatoire.
genre 0,015668
et il faut que l'élève trouve que ça fait 1,5668 .10^"-2"
donc bref je compare deux nombres.
celuidonné par l'élève : 1,5668
et celui donnée par le script : 1,5668
et de temps en temps le script affiche faux alors que ce sont les mêmes nombres.
J'ai fait afficher les deux nombres par la page, il s'agit bien des deux nombres ci dessus.
mais quand je fais leur différence : j'observe une différence d'environ 1E-16
Conclusion j'ai modifié mon script pour qu'il donne juste aux élèves si la différence entre les deux nombres est inférieur à 1E-15 (mais mathématiquement ça me gêne !)
Si ça intéresse, je peux fournir le script à qui veut !
[^] # Re: moi aussi
Posté par Cyber Kobold (site web personnel) . Évalué à -1.
parce que 0,00001 est écrit par PHP sous forme 1E-5 et que ça ne m'intéresse pas du tout dans le cas de mon script.
(je pose la question ici, vu que les forums me sont interdits faute de suffisament d'XP)
# ha les joies des virgules flottantes
Posté par jemore . Évalué à 1.
En java, un System.out.println(19.90*100) donnerait le meme genre d'erreur, c'est pour cela qu'il faut systématiquement un formateur (NumberFormat en l'occurence).
En PHP, on peut s'en sortir avec un printf :
echo (int)(sprintf("%F", 19.90*100));
Mais ca me semble un peu gruick quand meme.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.