IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

addition de Double


Sujet :

Langage Java

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 78
    Par défaut addition de Double
    Bonjour,

    Je m'adresse à la communauté car un problème m'empêche de dormir en ce moment... je n'arrive pas à comprendre.
    Voici le bout de code fautif:

    Double d1 = new Double(6.33);
    Double d2 = new Double(6.33);
    Double d3 = new Double(10);
    double d4 = d3.doubleValue() + d1.doubleValue() + d2.doubleValue();
    System.out.println("" +d4);

    J'obtiens 22.65999999999999997 au lieu de 22.66 !!!!!!!!
    Par contre si je fais:
    double d4 = d1.doubleValue() + d2.doubleValue() + d3.doubleValue();
    J'obtiens le bon résultat, 22.66 (j'ai d'abord ajouté le 10)

    Après avoir fait différents tests et cherché, je ne trouve pas l'explication..

    Alors je m'en remets à vos avis d'experts!!

    Merci!

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 109
    Par défaut
    Quel que soit le langage de programmation, les calculs en virgule flottante peuvent générer des erreurs d'arrondi. C'est inhérent à la représentation en mémoire des nombre réels.

    A priori, dans le premier cas tu effectues (d3 + d2) + d1, qui génère une erreur d'arrondi. Ce n'est pas le cas pour ton second test, qui correspond à l'opération (d1 + d2) + d3.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 78
    Par défaut
    Merci pour ta réponse.
    Ce qui me gêne néanmoins, c'est qu'un arrondi se produise sur un calcul aussi simple et avec des nombres aussi petit que 6.33 + 6.33 +10

    Je savais qu'on pouvais obtenir des arrondis avec certains chiffres extremement grand, d'autres très petits, les casting double - float etc ...
    Mais quand même, un double est sur 64 bits!!! et même si on tient compte de la représentation en virgule flottante, ça me surprend qu'on ait des arrondis sur des calculs avec des chiffres ni très petits, ni très grands, ni avec un grand nombre de chiffres après la virgule, et qui plus est avec un calcul censé donner un résultat avec 2 chiffres après la virgule (on n'est pas dans le cas de 1 / 3 = 0.3333333333333333333333333333 ....)

    A mon avis, il ya une explication simple et rationnelle, mais laquelle?

  4. #4
    Membre expérimenté Avatar de fremsoi
    Inscrit en
    Août 2003
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 201
    Par défaut
    J'suis curieux de comprendre aussi

    Car si on fait
    d1 + d2 ==> 12.6 ( et pas 12.6666666669..)
    d3 + d2 ==> 16.3 ( et pas 16.2222222229..)
    d3 + d1 pareil

    Donc là je piges et rente qd même bleuffer

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 104
    Par défaut
    Citation Envoyé par badjojo
    A mon avis, il ya une explication simple et rationnelle, mais laquelle?
    Un double Java suit la norme IEEE-754 où un nombre à virgule flottante est représenté avec une mantisse sur une cinquantaine de bits et un exposant représentant une puissance de 2 sur une dizaine de bits.

    Des valeurs comme 1, 1.5, 1.125 ou 633 sont représentées sans aucune perte de précision car elles peuvent être écrites sous la forme de 1*(2**0), 3*(2**-1), 9*(2**-3), 633*(2**0).

    Par contre, une valeur comme 6.33 subit une erreur d'arrondi due au fait qu'il n'y a aucune façon de l'écrire exactement sous la forme de "mantisse * (2 puissance exposant)".

  6. #6
    Membre expérimenté Avatar de fremsoi
    Inscrit en
    Août 2003
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 201
    Par défaut
    Ok mais pourquoi alors
    6.33 + 6.33 donne 12.66 ( donc pas d'erreur d'arrondi )
    et 10 + 6.33 + 6.33 provoque une erreur ( alors que 10 pose pas de problème )

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 109
    Par défaut
    parce que quand tu évalues 10 + 6.33 + 6.33, le programme effectue en réalité
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    10 + 6.33 + 6.33 = 16.33 + 6.33
    ce qui est différent de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    6.33 + 6.33 + 10 = 12.66 + 10
    Chaque étape intermédiaire est suceptible de générer une erreur d'arrondi différente. Tu ne remarques l'erreur d'arrondi globale que quand la cumulation des erreurs intermédiaires dépasse un certain seuil.

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 94
    Par défaut
    salut,
    étonnant en effet, mais j'ai du mal à croire qu'il n'y a pas solution .... :

  9. #9
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 901
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 901
    Billets dans le blog
    54
    Par défaut
    Tu peux utiliser BigDecimal à la place mais ca n'enlève pas le problème, ca ne fait que le cacher/retarder en augmentant encore plus la précision.

    Egalement, s'il s'agit juste de problème d'affichage (et non de problème de précision des calculs, comme dans une simulation scientifique) ; ce genre de chose peut vite être "effacée" en utilisant un NumberFormat ou un DecimalFormat correctement configuré.

    Ce problème de précision apparait aussi dans les simul de population de poissons des scientifiques pour lesquels je bosse (mais sur des nombres beaucoup plus grand). Il est courrament admis qu'en général les erreurs de precision se contre-balancent les unes les autres d'elle même lors de (très) long calculs. Ce qui fait que le résultat est tout de même relativement précis et corrects.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 78
    Par défaut
    Merci pour vos lumières.. on avance un peu, même si on n'a toujours pas la réponse...

    En effet, comment est-il possible que pour des nombres si banals, et des calculs si simples il puisse y avoir erreur d'arrondi.

    Il s'agit d'un calcul extrêmement simple, qui devrait pouvoir être réalisé correctement avec des Floats, des Doubles, des BigDecimaux...
    On est presque au niveau d'un " 1 + 1 = 2". Imaginez si une erreur pouvait se produire sur ce calcul.. quelle serait la fiabilité des logiciels en circulation???!!!

    Je pense qu'il doit exister une faille dans ma façon de calculer avec les double ou qqe chose comme ça... sinon, ça serait grave.

    Je travaille sur une application de gestion, ou des montants sont calculés au centime près.. juridiquement et fiscalement, il est important que les montants soient justes. alors si 10 + 6.33 + 6.33 donne autre chose que 22.66, je ne suis pas sorti de l'auberge!!!!

  11. #11
    Membre Expert
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Par défaut
    Si effectivement tes calculs sont dans le domaine de la gestion, je te conseille d'éviter les floats ou les doubles.

    Prends-toi quelques heures à te documenter sur les problèmes d'arrondi, sur la classe BigDecimal ou peut être il existe des classes spécifiques aux calculs financiers.

    Je pense que tu amortiras rapidement ces heures.

    Un lien intéressant. Il en existe des centaines sur ce sujet. est ton ami.

  12. #12
    Membre expérimenté Avatar de vincent63
    Inscrit en
    Octobre 2005
    Messages
    198
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 198
    Par défaut
    'jour,
    je trouve ce sujet assez intéressant. Surtout que si on fait qques tests, on se rend compte que l'ordre n'est pas le seul facteur qui influence le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    a = 1.33 b = 1.33 c = 1.0 Sum (a+b+c)= 3.66 Sum (c+a+b)= 3.66
     a = 2.33 b = 2.33 c = 2.0 Sum (a+b+c)= 6.66 Sum (c+a+b)= 6.66
     a = 3.33 b = 3.33 c = 3.0 Sum (a+b+c)= 9.66 Sum (c+a+b)= 9.66
     a = 4.33 b = 4.33 c = 4.0 Sum (a+b+c)= 12.66 Sum (c+a+b)= 12.66
     a = 5.33 b = 5.33 c = 5.0 Sum (a+b+c)= 15.66 Sum (c+a+b)= 15.66
     a = 6.33 b = 6.33 c = 6.0 Sum (a+b+c)= 18.66 Sum (c+a+b)= 18.66
     a = 7.33 b = 7.33 c = 7.0 Sum (a+b+c)= 21.66 Sum (c+a+b)= 21.66
     a = 8.33 b = 8.33 c = 8.0 Sum (a+b+c)= 24.66 Sum (c+a+b)= 24.659999999999997
     a = 9.33 b = 9.33 c = 9.0 Sum (a+b+c)= 27.66 Sum (c+a+b)= 27.659999999999997
     a = 10.33 b = 10.33 c = 10.0 Sum (a+b+c)= 30.66 Sum (c+a+b)= 30.659999999999997
    Je serais curieux d'avoir l'explication exact du phénomène...

  13. #13
    Membre Expert
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Par défaut
    Citation Envoyé par vincent63
    'jour,
    je trouve ce sujet assez intéressant. Surtout que si on fait qques tests, on se rend compte que l'ordre n'est pas le seul facteur qui influence le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    a = 1.33 b = 1.33 c = 1.0 Sum (a+b+c)= 3.66 Sum (c+a+b)= 3.66
     a = 2.33 b = 2.33 c = 2.0 Sum (a+b+c)= 6.66 Sum (c+a+b)= 6.66
     a = 3.33 b = 3.33 c = 3.0 Sum (a+b+c)= 9.66 Sum (c+a+b)= 9.66
     a = 4.33 b = 4.33 c = 4.0 Sum (a+b+c)= 12.66 Sum (c+a+b)= 12.66
     a = 5.33 b = 5.33 c = 5.0 Sum (a+b+c)= 15.66 Sum (c+a+b)= 15.66
     a = 6.33 b = 6.33 c = 6.0 Sum (a+b+c)= 18.66 Sum (c+a+b)= 18.66
     a = 7.33 b = 7.33 c = 7.0 Sum (a+b+c)= 21.66 Sum (c+a+b)= 21.66
     a = 8.33 b = 8.33 c = 8.0 Sum (a+b+c)= 24.66 Sum (c+a+b)= 24.659999999999997
     a = 9.33 b = 9.33 c = 9.0 Sum (a+b+c)= 27.66 Sum (c+a+b)= 27.659999999999997
     a = 10.33 b = 10.33 c = 10.0 Sum (a+b+c)= 30.66 Sum (c+a+b)= 30.659999999999997
    Je serais curieux d'avoir l'explication exact du phénomène...
    Essaie d'effectuer ces calculs avec la même représentation qu'un ordinateur et tu seras surpris que tu arriveras au même résultats affichés.

  14. #14
    Membre Expert
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Par défaut
    Je suis étonné du résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    		float sumFloat = 8.0f + 8.33f + 8.33f;
            double sumDouble = 8.0d + 8.33d + 8.33d;
     
            System.out.println("Float:  " + sumFloat);
            System.out.println("Double: " + sumDouble);
    Résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Float:  24.66
    Double: 24.65999984741211

  15. #15
    FFF
    FFF est déconnecté
    Membre éclairé Avatar de FFF
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    342
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 342
    Par défaut Re: [addition de Double] Enigme !!
    Citation Envoyé par badjojo
    Bonjour,

    Je m'adresse à la communauté car un problème m'empêche de dormir en ce moment... je n'arrive pas à comprendre.
    Voici le bout de code fautif:

    Double d1 = new Double(6.33);
    Double d2 = new Double(6.33);
    Double d3 = new Double(10);
    double d4 = d3.doubleValue() + d1.doubleValue() + d2.doubleValue();
    System.out.println("" +d4);

    J'obtiens 22.65999999999999997 au lieu de 22.66 !!!!!!!!
    Par contre si je fais:
    double d4 = d1.doubleValue() + d2.doubleValue() + d3.doubleValue();
    J'obtiens le bon résultat, 22.66 (j'ai d'abord ajouté le 10)

    Après avoir fait différents tests et cherché, je ne trouve pas l'explication..

    Alors je m'en remets à vos avis d'experts!!

    Merci!
    tu as essayé avec du transtypage :
    d4=(double)d1+(double)d2+... ?

    ou tout simplement :
    d4=d1+d2+d3

    puisque tes données sont de même type

    cette erreur provient en général d'une imprecision due à la conversion float -> double ou double -> double

    pour éviter ces problèmes il faut éviter au maximum de passer d'un type de données à un autre même si ce type reste le même !
    Un post a été résolu sur un sujet similaire concernant le PHP...

    ++

  16. #16
    Membre expérimenté Avatar de vincent63
    Inscrit en
    Octobre 2005
    Messages
    198
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 198
    Par défaut
    Bon, voilà un bout de réponse...

    http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 94
    Par défaut
    oui, cependant je remarque que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    float sumFloat = 8.0f + 8.33f + 8.33f; 
    double sumDouble = 8.0d + 8.33d + 8.33d; 
    double sumDouble2 = 8.33d + 8.33d + 8.0d; 
    System.out.println("Float:  " + sumFloat); 
    System.out.println("Double: " + sumDouble); 
    System.out.println("Double2: " + sumDouble2);
    donne toujours
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Float:      24.6
    Double:   24.659999999999997
    Double2: 24.66
    d'ailleurs, pourquoi une cette différence avec le résultat précedent de
    Double: 24.65999984741211 entre deux ordinateurs ????
    doit on en conclure que les float sont plus appropriés ici ... :

  18. #18
    Membre expérimenté Avatar de vincent63
    Inscrit en
    Octobre 2005
    Messages
    198
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 198
    Par défaut
    J'suis pas sûr que l'on puisse dire que les float soient plus appropriés.

    Entre 24.66 et 24.6, il y a une différence de 0.06

    Pour les double, la différence est moins grande.

  19. #19
    FFF
    FFF est déconnecté
    Membre éclairé Avatar de FFF
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    342
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 342
    Par défaut
    pas facile...
    j'ai déjà eu moi aussi des soucis de ce type pour des calculs scientifiques. et j'en ai retenu que pour avoir des calculs numériques précis, il fallait être très rigoureux dans l'écriture des doubles (même les chiffres doivent être écrits avec précision) sinon l'ordi te mets ce qu'il veut là où il y a des manques.
    Manipuler des doubles c'est chaud !!!
    Plein de scientifiques ont écrit des doc sur le calcul numérique, il faut faire une recherche la dessus sur google.

  20. #20
    Membre éclairé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 94
    Par défaut
    oui, bien sur, en plus j'ai vu ton post avec le lien qu'aprés avoir envoyé le mien. la réponse me parait bien être dans ce pdf, quand au fait que 2 ordinateurs n'obtiennent pas le même résultat sur l'opération (cf.FFF),
    que dire ?

Discussions similaires

  1. Addition avec des variables "double"
    Par dieu08 dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 04/10/2012, 16h29
  2. [double] problème addition java
    Par franfr57 dans le forum Langage
    Réponses: 1
    Dernier message: 26/03/2009, 17h55
  3. [imprecis]Réaliser a^n avec seulement l'opérateur d'addition
    Par Amon dans le forum Algorithmes et structures de données
    Réponses: 18
    Dernier message: 08/11/2002, 22h22
  4. String -> long double (_strlold ?)
    Par haypo dans le forum C
    Réponses: 7
    Dernier message: 25/07/2002, 20h22
  5. Réponses: 3
    Dernier message: 12/06/2002, 21h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo