Forum Programmation.web javascript bug sur une addition ?

Posté par (page perso) .
Tags : aucun
0
19
jan.
2006
Bonjour,

J'essai depuis quelque temps d'additionner des float avec javascript.
Mais le resultat est quelque peu incertain, même avec des nombres assez simple :
0.1+0.1 = 0.2 (jusque là normal...)
0.1+0.1+0.1 = 0.3000000000000004 (?????)
par contre :
0.1+0.1+0.05+0.05 = 0.3
mais
0.1+0.1+0.01+0.09 = 0.3000000000000004

mais
0.2 + 0.4 = 0.6000000000000001
et
0.1+0.7 = 7.999999999999999

Mais les erreurs se corrigent 'd'elles même'
0.1+0.1+0.1 donne donc 0.3000000000000004
0.1+0.1+0.1+0.1 donne lui 0.4
0.1+0.1+0.1+0.1+0.1=0.5
0.1+0.1+0.1+0.1+0.1+0.1=0.6
0.1+0.1+0.1+0.1+0.1+0.1+0.1=0.7
0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1=0.7999999999999999
erreur jusque:
0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 = 1.2

Y'aurais pas comme un problème par hasard ?
J'ai testé sous windows, sous linux, avec ie ou firefox pareil.

Quelqu'un sait d'où ça vient ?

Le problème c'est que ça devient dur de faire confiance à javascript...
  • # Problème des nombres flotants

    Posté par . Évalué à 6.

    Problème commun à toutes les représentations des nombres "à virgule flottante".

    C'est commun à tout les languages, pas seulement au javascript.

    voir http://fr.wikipedia.org/wiki/Virgule_flottante :

    Les calculs en virgule flottante sont pratiques, mais présentent trois désagréments :
    # leur précision limitée, qui se traduit par des arrondis qui peuvent s'accumuler de façon gênante. Pour cette raison, les travaux de comptabilité ne sont pas effectués en virgule flottante, même pour la fortune personnelle de Bill Gates, car tout doit y tomber juste au centime près.
    # ...
    • [^] # Re: Problème des nombres flotants

      Posté par (page perso) . Évalué à 1.

      je pensais bien que ça venait d'un problème de float commun à un peu tous les langages (mais je n'avais pas fait de tests dans d'autres languages)

      Que 1/3 * 3 (comme plus bas) ne fasse pas 1 ne me perturbe pas du tout, je sais bien qu'on est pas en précision absolue (ou plutôt en fraction)
      Mais je comprend quand même pas trop comment 0.2 + 0.1 ne fait pas 0.3, où dans ce cas on n'a pas du tout de problème de précision limitée.

      m'enfin, ça m'a bien supris, rigolé et maintenant je joue avec round ou des équivalents ;-)
  • # Précision des nombres en virgule flottante

    Posté par (page perso) . Évalué à 4.

    Tu as fait le test en C ?
    #include <stdio.h>
    int main(void) {
    	float a, b, c, d;
    
    	a = 0.1f;
    	b = 0.1f;
    	c = a + b;
    	printf("0.1f + 0.1f = %.12f\n", c);
    
    	c = 0.1f;
    	d = a + b + c;
    	printf("0.1f + 0.1f + 0.1f = %.12f\n", d);
    
    	return 0;
    }
    
    compilation et exécution :
    [florent:~/Code/testfloat]$ gcc main.c
    [florent:~/Code/testfloat]$ ./a.out
    0.1f + 0.1f = 0.200000002980
    0.1f + 0.1f + 0.1f = 0.300000011921
    
    Pas de quoi s'affoler et perdre confiance en javascript, donc ... :)
  • # javascript bug sur une addition ?

    Posté par . Évalué à 1.

    Je ne connais pas le javascript en particulier, mais c'est un problème classique en informatique.

    Pour comprendre, essaye "d'écrire" 1/3 en décimal. Tu vas noter 0,33333 avec plus ou moins de chiffre, mais avec forcément un erreur.

    Si tu additionnes 1/3, 1/3 et 1/3 en décimal, donc 3 fois 0,33333, tu n'auras pas 1, mais 0,99999.

    En informatique, quand on code un décimal, ou float en anglais, on a un problème du même ordre, mais avec les multiples de 2, du au codage avec un exposant.

    C'est pour ça qu'il faut faire attention au choix entier ou décimaux, et faire attention quand on mélange les 2 types.
    • [^] # Re: javascript bug sur une addition ?

      Posté par . Évalué à 0.

      En tout cas moi j'attend toujours une explication qui ressemble à quelque chose pour ce truc :

      x = 0.999999999999...
      <=> 10x = 9.9999999999999...
      <=> 10x - x = 9x = 9.0
      <=> x = 1.0
      Donc 1.0 = 0.9999999999....
      • [^] # Re: javascript bug sur une addition ?

        Posté par . Évalué à 1.

        Réduis le nombre de 9 et tu comprendras :
        x= 0.99999
        10x = 9.9999
        10x -x = 9x = 8.99991
        x = 0.99999
        Donc 0.99999 = 0.99999 et tout va bien
      • [^] # 0.9999999...

        Posté par . Évalué à 2.

        rien a voir.

        et oui, effectivement, 1 == 0.99999999999999...
        en mathematique, tout simplement car tu ne peux pas trouver un autre réel à intercaller entre 1 et 0.9999999...
        • [^] # Re: 0.9999999...

          Posté par (page perso) . Évalué à 2.

          Tiens, je croyais naïvement qu'au contraire, les réels permettaient toujours d'intercaler un nombre entre deux autres :)
          • [^] # Re: 0.9999999...

            Posté par (page perso) . Évalué à 2.

            C'est aussi ce qu'il me semble : je crois qu'il s'agit plus d'un problème de *représentation* des réels...
          • [^] # Commentaire supprimé

            Posté par . Évalué à 1.

            Ce commentaire a été supprimé par l'équipe de modération.

          • [^] # démo de 1=0,99999......

            Posté par . Évalué à 1.

            Et pour la démo de 1=0,999999........

            Prenons x= 0.99999......
            donc 10x = 9.9999.......
            donc 10x -x = 9x = 9
            donc x = 1
            Donc 0.99999...... = 1

            Et oui, 1=0.999999...... mais on peut effectivement intercaler un réel ente deux autres, pour peu qu'ils soient différents !!
            • [^] # Re: démo de 1=0,99999......

              Posté par . Évalué à 2.

              la bidouille du "fois dix" n'est pas une demonstration, d'apres ce qu'avais dis mon prof de math il y a dix ans.
              la demonstration, c'est le fait qu'on NE PEUT PAS intercaller un nombre entre 1 et 0.9999...
              forcement c'est pas la demonstration la plus visible et plus comprehensible pour les classes de primaire (heu pardon c'est sortis tout seul).
              si x != y (x<y) alors il existe un z tel que x<z<y dans le corps des reels.
              et par contraposé : s'il n'existe pas ce z, c'est que x==y.

              "<" representant la relation d'ordre dans R.
              contraposé : a => b donc non-b => non-a

              ouf, c'est vieux tout ca :)
              • [^] # Re: démo de 1=0,99999......

                Posté par . Évalué à 1.

                sans vouloir être méchant, ton prof de math ne savait pas de quoi il parlait :
                cette démo n'a rien d'une bidouille et se trouve dans tous les ouvrages de math concernant le sujet ....
                D'ailleurs, si qqu'un peut trouver une qquonque erreur de raisonnement dans cette "célèbre" démo, qu'il me jette la première pierre !
                • [^] # Re: démo de 1=0,99999......

                  Posté par . Évalué à 2.

                  peut être, je tiens celà de ma prof de math de classes preparatoires TA du lycée edouad branly a lyon 5e le point du jour. en 1993. (j'ai oublié son nom). Je ne sais pas si elle est nulle, mais j'ai vu les math de maniere differentes apres elle.

                  alors ca ne vaut pas grand chose de dire celà. mais quand on vois que de nos jours ont se justifie a coups de google-rank :)

                  a et au passage, quand je vois celà :
                  10x -x = 9x = 8.99991
                  ca me fait doucement rire. (le 1 à droite!!!!) oui je sais c'est pas ta demonstration, mais je releve.

                  maintenant ta demo est difficile tout simplement parceque quand tu fait 10x, j'aimerais savoir sur quoi tu te base pour dire que ca fait 9.9999... sur quel axiome, theoreme, definition ?
                  je vais et le dire tu te base sur uen recete de cuisine : "quand on multiplie par dix, on deplace la virgule a droite (CM1)" et bien, des demonstration ca ne se repose pas sur uen recete, désolé. surtout quand on a un arsenal pour effectuer cette demo !

                  une autre demonstration peut être :
                  0.9999... = limite (n->infini) de Sigma(i de 1 à n) 9/10^i
                  le sigma permet d'ecrire chacun de "9" dans le nombre, et quand on efectue la limite, on a bien "1".
                  • [^] # Re: démo de 1=0,99999......

                    Posté par . Évalué à 1.

                    bon, ben autant te l'annoncer, tu parles à un prof de math.

                    1)
                    a et au passage, quand je vois celà :

                    10x -x = 9x = 8.99991

                    ca me fait doucement rire. (le 1 à droite!!!!) oui je sais c'est pas ta demonstration, mais je releve.

                    Lis bien qui a écrit ce post, et tu verras que ce n'est pas le mien

                    2)e vais et le dire tu te base sur uen recete de cuisine : "quand on multiplie par dix, on deplace la virgule a droite (CM1)" et bien, des demonstration ca ne se repose pas sur uen recete, désolé. surtout quand on a un arsenal pour effectuer cette demo !

                    Oui, c'est ce qu'on dit aux gamins pour qu'ils retiennent, mais c'est basé sur la définition même de l'écriture en base 10 des nombres réels !!
                    (en résumé : 0,999..=0*10^0 + 9*10^-1 +... et donc, en mulipliant par 10, tu "décales" ttes tes puissances de 1 rang ( Ah, au fait, cette série étant convergente, je puis me permettre de la muliplier par 10))

                    3) Cette démo (celle de mon post) est enseignée dans ttes les classes prépas pour 2 raisons: sa simplicité et sa rigueur mathématique !!

                    4) Pour ce qui de linux, j'écoute et je marche sur des oeufs. Pour ce qui est des maths, tu devrais lire des bouquins de math avt de dire n'importe quoi, et de rappeller tes souvenirs vagues et complètement confus de tes cours de math du Lycée.

                    A bon entendeur, salut.
          • [^] # Re: 0.9999999...

            Posté par . Évalué à 2.

            Tiens, je croyais naïvement qu'au contraire, les réels permettaient toujours d'intercaler un nombre entre deux autres :)


            ben, oui, mon gros malin... c'est justement là la demonstration.
            puisque tu ne peux pas c'est qu'il s'agit du même nombre, relis ca que j'ai ecrit :)
      • [^] # Re: javascript bug sur une addition ?

        Posté par (page perso) . Évalué à 4.

        0.999999 est représenté par une somme indicé jusqu'a l'infini du terme 9*10^-i .

        et donc par construction, on montre que si il existait un reel r entre sigma 9*10^-i à l'infini et 1 alors il existe un majorant de ce reel r ayant pour ecriture sigma 9*10^-i .

        dit autrement, 1- Sigma 9*10^-i = 1*10-infini .

        et 1*10-infini est impossible dans |R et donc on considere qu'a la limite il vaut 0 . et là, est le probleme de |R.

        |R est un ensemble excessivement dense, et selon Turing il me semble, nous utilisons exactement 0% des nombres disponibles dans |R.

        Ce 0% peut vous sembler choquant, et il s'explique tres simplement les entiers et les rationnels couvrent 0% de |R . le cardinal de l'ensemble |N et de l'ensemble |Q| vaut Aleph0 celui de |R vaut aleph1 qui se calcul comme 2^aleph0 .

        nous savons que x/2^x est incalculable à l'infini mais a la limite est assimilable à 0 .

        pourtant nous en manipulons enormement et nous savons qu'il y en a une infinité. c'est une des absurdités de |R.

        oui il y a une difference formelle entre sigma 9*10-i et 1 mais elle n'est pas quantifiable dans |R . et nous ne pouvons pas construire d'ensemble numerique autre permettant d'aller au dela à partir de ZF ou ZFC ( merci Gödel ;) ).

        l'histoire de ces petits rien négligeable commence avec Leibniz et Newton sur le calcul infinitésimal et intégral.

        Maintenant, si l'on en croit un roman de Arthur C Clarke ( auteur de sf et père des telecommunication par satellite geostationaire ), un jour viendra ou l'on saura faire la difference entre 0+ et 0- ( donc entre sigma 9*10-i et 1 et 1+1*10-i ), et de cela en tirer suffisament d'energie pour sauver l'espece humaine de l'extinction par la disparition du soleil. ... mais comme qui dirait, c'est de la science fiction ...

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.