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 régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 78
    Points : 81
    Points
    81
    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 régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 109
    Points : 122
    Points
    122
    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 régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 78
    Points : 81
    Points
    81
    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 actif Avatar de fremsoi
    Inscrit en
    Août 2003
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 201
    Points : 217
    Points
    217
    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 habitué
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 104
    Points : 140
    Points
    140
    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 actif Avatar de fremsoi
    Inscrit en
    Août 2003
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 201
    Points : 217
    Points
    217
    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 régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 109
    Points : 122
    Points
    122
    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 régulier
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 94
    Points : 92
    Points
    92
    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 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    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 régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 78
    Points : 81
    Points
    81
    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 chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 413
    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 413
    Points : 1 993
    Points
    1 993
    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.
    Bien le bonjour chez vous
    Jowo

  12. #12
    Membre actif Avatar de vincent63
    Inscrit en
    Octobre 2005
    Messages
    198
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 198
    Points : 205
    Points
    205
    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...
    "Ils ne savaient pas que c'était impossible... alors ils l'ont fait." Mark Twain

  13. #13
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 413
    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 413
    Points : 1 993
    Points
    1 993
    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.
    Bien le bonjour chez vous
    Jowo

  14. #14
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 413
    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 413
    Points : 1 993
    Points
    1 993
    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
    Bien le bonjour chez vous
    Jowo

  15. #15
    FFF
    FFF est déconnecté
    Membre actif 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
    Points : 282
    Points
    282
    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 actif Avatar de vincent63
    Inscrit en
    Octobre 2005
    Messages
    198
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 198
    Points : 205
    Points
    205
    Par défaut
    Bon, voilà un bout de réponse...

    http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf
    "Ils ne savaient pas que c'était impossible... alors ils l'ont fait." Mark Twain

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 94
    Points : 92
    Points
    92
    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 actif Avatar de vincent63
    Inscrit en
    Octobre 2005
    Messages
    198
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 198
    Points : 205
    Points
    205
    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.
    "Ils ne savaient pas que c'était impossible... alors ils l'ont fait." Mark Twain

  19. #19
    FFF
    FFF est déconnecté
    Membre actif 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
    Points : 282
    Points
    282
    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 régulier
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 94
    Points : 92
    Points
    92
    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