Journal Java et les double

Posté par  .
Étiquettes : aucune
0
17
mar.
2004
double nb = 9.37;
nb = nb * 100;
---> nb donne 936.99999999999

Bien la precision des double en Java !!! :)
  • # Re: Java et les double

    Posté par  (site web personnel) . Évalué à 3.

    C'est un calcul sur pentium ?

    ===>[]
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      Oui, sur un Intel Pentium IV.
      Est-ce lie au processeur ? La javadoc semble indiquer que les doubles ne garantissent pas la precision..
      • [^] # Re: Java et les double

        Posté par  . Évalué à 2.

        Je crois que t'as pas compris. Renseigne-toi sur l'histoire du bug du pentium (premier du nom).
        • [^] # Re: Java et les double

          Posté par  . Évalué à 2.

          Celui a fait qu'ils l'ont appele pentium et pas 586, parce qu'ils ont fait l'operation 486 + 100 avec et que le resultat de 485.999999999999 ne leur paraissait pas tres bon niveau marketing ?
  • # Re: Java et les double

    Posté par  . Évalué à 10.

    "java et les doubles"

    tout ça me fait penser à un personnage clé de DLFP
  • # Re: Java et les double

    Posté par  . Évalué à 4.

    C'est tout à fait normal et pas forcément lié à java : ta précision est de 9.37-9.3699999999999 , soit pas beaucoup. Les calculs en nb flottants sont de toutes manières approchés (le nombre de valeurs possibles étant fini). Après, si tu veux en faire un affichage correct (écrire X+1 au lieu de X.999999999999), tu peux écrire une fonction adaptée.
    • [^] # Re: Java et les double

      Posté par  . Évalué à 6.

      En fait c'est pas tant le fait que le nombre de combinaisons soit limité qui pose problème dans le cas précis, mais celui qu'un nombre peut être fini dans une base et pas dans une autre.

      Exemple:

      1.5d = 1.1b
      1.2d = 1.0011001100110011 ...

      L'arrondi se fait probablement, dans ton cas, en fonction de la valeur du dernier bit du champs (le bit de poids faible de la mantisse, à droite) qui ici doit probablement être à 1. Quand tu multiples par 100, tu introduis probablement des zéros à la fin de ta mantisse, qui du coup doit être arrondi au plus faible. Il existe plusieurs manières de traiter cela. Quoiqu'il en soit, tu dois bien avoir un fonction round() qui sert à gérer cela (je connais pas le Java).
      • [^] # Re: Java et les double

        Posté par  . Évalué à 3.

        Exemple encore plus simple (à mon avis)

        1/3=0.33333333333333333333333333.... en base 10
        1/3=.1 en base 3
        • [^] # Re: Java et les double

          Posté par  . Évalué à 3.

          Tout-à-fait, l'exemple 1/3 est l'exemple de nombre non-fini le plus courant en maths, mais il s'agissait de donner l'exemple de quelque chose qui provoque ce cas en binaire et qui provoque potentiellement une erreur avec les nombres à virgule flottante.

          De plus, 1.5 et 1.2 sont non seulement deux nombres finis en décimal, mais qui en plus ont l'air très faciles à coder. Qui aurait crû qu'un ordinateur ne peut exactement se représenter 1.2 ? :-)
  • # Re: Java et les double

    Posté par  . Évalué à 5.

    Je vais te donner un probleme a resoudre :

    Trouves moi un moyen de representer dans un champs de disons 32bits, toutes les valeurs 0 a 1.

    0.1, 0.01, 0.0003, 0.000000005, etc....

    Si tu y arrives, je te files un prix nobel.

    Si tu n'y arrives pas, ben tu auras compris pourquoi Java n'y arrive pas non plus
    • [^] # Re: Java et les double

      Posté par  (site web personnel) . Évalué à 6.

      Si tu y arrives, je te files un prix nobel.
      Regardez la puissance de Microsoft ! Chacun de leurs employés peut délivrer un prix Nobel. Après on nous traite de paranos :-)
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      Ni d'ailleurs le C, le C++ etc ...
      Bref, faut juste savoir qu'un double ne peut prendre qu'un ensemble de valeurs finies, et donc va faire loger un resultat theorique dans la valeur la plus proche qu'il peut representer ...
      • [^] # Re: Java et les double

        Posté par  . Évalué à 3.

        Ben justement non.

        Un gros problème de pas mal de bibliothèques numériques et de processeurs, c'est qu'ils sont optimisés surtout pour la vitesse. Résultat, ils ne garantissent absolument rien sur la précision du résultat. Il est très fréquent de perdre 5 bits de précision sur une division. Il existe une norme IEEE qui spécifie l'addition, la soustraction, la multiplication et la division mais rien de plus et peu de processeurs l'implémentent parfaitement.
  • # Re: Java et les double

    Posté par  (site web personnel) . Évalué à 3.

    rien à voir avec java, c'est juste les nombres à virgule flotante avec un ordi.
    Fais le test en C
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      Perl Uber Alles ...
      > perl -e '$nb=9.37; $nb*=100; print $nb;'
      937
      • [^] # Re: Java et les double

        Posté par  . Évalué à 1.

        Pfff, tricheur, le Perl travaille en BCD (ou alors je dis n'importe quoi)
        • [^] # Re: Java et les double

          Posté par  . Évalué à 2.

          Pire, il arrondi le résultat :

          perl -e '$nb=9.37; $nb*=100; printf "%.15f", $nb;'
          936.999999999999886
          • [^] # Re: Java et les double

            Posté par  . Évalué à 2.

            Pas pire, mieux.

            Perl fait ce qu'on attend, pas ce que la machine veut bien faire. C'est en ça que c'est un langage génial...
    • [^] # Re: Java et les double

      Posté par  (site web personnel) . Évalué à 1.

      Bizarre, ça marche en C (VC6 et gcc), mais pas en Python. Pourtant j'ai viré l'optimisation... J'ai pas envie de faire la conversion à la main (mantisse, exposant, signe) qui est laissée comme exercice au lecteur :-)
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      Avec gcc 2.96 :
      #include <iostream>
      int main()
      {
          float f = 9.37f;
          double d = 9.37;
          f = f * 100;
          d = d * 100;
          cout << f << endl;
          cout << d << endl;
          return 0;
      }
      
      donne bien le résultat attendu :
      937
      937
      
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      En maple ça marche bien ;)
  • # Re: Java et les double

    Posté par  . Évalué à 2.

    Avec float par contre ça donne 937 :)

    float nb = 9.37f;
    nb = nb * 100;

    ---> nb = 937.0
  • # Re: Java et les double

    Posté par  . Évalué à 4.

    Ce n'est pas que un problème de précision, mais aussi d'affichage. Ne fais pas un System.out.println("valeur=" + nb), mais utilise un formateur. Je te laisse chercher dans la javadoc comment faire...
  • # Re: Java et les double

    Posté par  . Évalué à 4.

    Pour être vachement plus précis, tu as le BigDecimal (ds java.math) :
    BigDecimal nb = new BigDecimal(9.37);
    BigDecimal cent = new BigDecimal(100);
    nb = nb.mutliply(cent);

    -> nb.toString() donne 937.000

    (BigDecimal accepte des double ou des String dans son contructeur)
  • # Re: Java et les double

    Posté par  . Évalué à 7.

    936.999999....9 = 937 de toute facon...
    je m'explique :
    x = 936.999999...9
    10x = 9369.99999........
    9x=8433

    donc : x= 8433/9 = 937

    Donc moi jvois pas ou est le probleme ;)

    ok ok je sors ... => [ -]
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      eh eh ça fait longtemps que je l'avais pas vu le coup de 0.999... = 1 :-)
      ça me rappelle la fac.
      • [^] # Re: Java et les double

        Posté par  . Évalué à -1.

        ouais moi aussi
        le coup du tres grand prof de math qui nous dit de faire le calcul en vitesse en considerant que pi vaut 3

        :-)
        • [^] # Re: Java et les double

          Posté par  . Évalué à 2.

          oui enfin sauf que la démonstration précédente est tout-à-fait exacte :-)
          • [^] # Re: Java et les double

            Posté par  . Évalué à 2.

            Je vais aussi me lancer dans une autre démo.

            x=1 et y=0.99999999999999999999999999...

            Si x!=y, alors x-y=e est strictement positif.

            Il existe n tel que 10^{-n}<e.

            Soit z=1-10^{-n}=0.9999999999999...99990000

            y>z donc x-y<x-z or x-z=10^{-n}<e

            donc e=x-y<e absurde donc x=y.
            • [^] # Re: Java et les double

              Posté par  . Évalué à 2.

              En d'autres termes


              n
              __
              LIM \ 9
              n-> +oo /__ ---------- = 1
              1 10^n


              Pt' 1 les maths en aa c'est pas facile
    • [^] # Re: Java et les double

      Posté par  . Évalué à 1.

      oui ça marche avec les "..."

      mais avec un nombre fini de 9 ça marche plus ton truc :o)
    • [^] # Re: Java et les double

      Posté par  . Évalué à 8.

      936.999999....9 = 937 de toute facon...

      attention! 936.999999.... = 937, mais 936.999999....9 != 937
      Si si c'est pas pareil!

Suivre le flux des commentaires

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