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 :

problème 22.72 - 12.72 retourne 9.99..


Sujet :

Langage Java

  1. #1
    Membre confirmé
    Avatar de jeha
    Inscrit en
    Octobre 2005
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 127
    Par défaut problème 22.72 - 12.72 retourne 9.99..
    bonjour,

    j'ai ce petit code qui doit retourner 10 mais j'ai comme résultat 9.999999999999998 !!!!!!!!!!!!!!!!!!!!!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        public static void main(String[] args) {
            // TODO code application logic here
             double amont= 22.72 - 12.72 ;
     
     
            System.out.println("Amont :"+amont );
        }
    merci pour votre aide et votre suggestion

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Par défaut
    C'est à cause de la représentation des floats. Tu trouveras surement ta réponse dans ce topic:
    http://www.developpez.net/forums/d34...-calcul-float/

  3. #3
    Membre confirmé
    Avatar de jeha
    Inscrit en
    Octobre 2005
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 127
    Par défaut
    merci chef pour votre réponse, donc la solution est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        public static void main(String[] args) {
            // TODO code application logic here
     
            BigDecimal valeur1 = new BigDecimal("22.72");
            BigDecimal valeur2 = new BigDecimal("12.72");
     
            BigDecimal resSoustraction = valeur1.subtract(valeur2);
     
     
     
     
            System.out.println("Amount :"+resSoustraction );
        }

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Ou alors, garder les floats (ou plutôt des double) et les faire afficher avec deux décimales maximum.

    Ou alors, calculer avec des ints et insérer une virgule avant les deux derniers chiffres à l'affichage.

    C'est quand même pas très pratique BigDecimal.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Avatar de jeha
    Inscrit en
    Octobre 2005
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 127
    Par défaut
    Ou alors, garder les floats (ou plutôt des double) et les faire afficher avec deux décimales maximum.

    Ou alors, calculer avec des ints et insérer une virgule avant les deux derniers chiffres à l'affichage.

    C'est quand même pas très pratique BigDecimal.

    c'est quoi donc la solution si la valeur retourner est faux, le 10 n'est pas le 9.999999999 !!!!!

    y a t'il une autre solution pour ce probleme de calcule

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Si tu affiches l'arrondi à deux décimales, ça fera bel et bien 10.

    Tu as vraiment besoin d'une précision à 9 décimales ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre émérite

    Homme Profil pro
    Directeur des systèmes d'information
    Inscrit en
    Septembre 2010
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Directeur des systèmes d'information

    Informations forums :
    Inscription : Septembre 2010
    Messages : 450
    Si vous moinsez, merci de répondre pour argumenter!
    Ma présentation

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Dans le cas présent, je pensais plutôt à un DecimalFormat. Si c'est pour faire ça, autant jongler dès le départ avec des BigDecimal et éluder le problème.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre émérite

    Homme Profil pro
    Directeur des systèmes d'information
    Inscrit en
    Septembre 2010
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Directeur des systèmes d'information

    Informations forums :
    Inscription : Septembre 2010
    Messages : 450
    Par défaut
    A voir selon d'où viennent ces doubles. Dans le code présent, ils sont instanciés par le dev dans le main, mais il s'agit d'un code exemple.

    Dans un vrai soft, ils peuvent provenir d'une fonction qu'on appelle dans une librairie, donc on n'a pas le choix d'obtenir un double en retour de cette fonction.

    Après, c'est sur que quand c'est possible, autant utiliser les bons types de données dès le départ, mais c'est un autre débat ^^
    Si vous moinsez, merci de répondre pour argumenter!
    Ma présentation

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Le bigdecimal ne résoudront pas le problème. La précision du type de données n'est pas en cause. Tes chiffres ne peuvent pas être réprésentés correctement dans un nombre binaire car en fraction binaire ils ont une réprésentation avec un nombre infini de décimal. C'est donc la conversion humain (décimal) / machine (binaire) qui introduit un légère erreur, légère erreur que l'on trouve dans le résultat.

    Dans ton cas, la seule manière de travailler est de réduire le nombre de décimale à l'affichage. Pour faire une analogie. Si on "vivait" en base 3 et que les ordinateurs étaient en base 10.

    On se dirait "1/3+1/3+1/3=1, naturelement". Mais quand on passerais sur un ordinateur on trouverais en fait "0.333333333"+0.333333333"+0.333333333" = "0.999999999". Dans notre cas, pour avoir 1 il faudrait arrondir le nombre, à 5 décomale, par exemple, et ca donnerais "1".

    Code d'exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
             double amont= 22.72 - 12.72 ;
             boolean result = amont==10.0;
             System.out.println("Amont "+amont+ "==10.0?"+result);
             amont= 22.72d - 12.72d ;
             System.out.println("Amont "+amont+ "==10.0?"+result);
             result = ((float)amont)==10.0;
             System.out.println("Amont "+amont+ "==10.0?"+result);
             BigDecimal bd = new BigDecimal(22.72).subtract(new BigDecimal(12.72));
             result = bd.doubleValue()==10.0;
             System.out.println("Amont "+bd.doubleValue()+ "==10.0?"+result);
             bd = new BigDecimal(22.72, new MathContext(5000)).subtract(new BigDecimal(12.72, new MathContext(5000)));
             result = bd.doubleValue()==10.0;
             System.out.println("Amont "+bd.doubleValue()+ "==10.0?"+result);
             bd = bd.round(new MathContext(15));
             result = bd.doubleValue()==10.0;
             System.out.println("Amont "+bd+ "==10.0?"+result);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Amont 9.999999999999998==10.0?false
    Amont 9.999999999999998==10.0?false
    Amont 9.999999999999998==10.0?true
    Amont 9.999999999999998==10.0?false
    Amont 9.999999999999998==10.0?false
    Amont 10.0000000000000==10.0?true

  11. #11
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Le bigdecimal ne résoudront pas le problème.
    Tout de même, leur manie de tout stocker dans un BigInteger d'une part, et de stocker l'emplacement de la virgule dans int d'autre part, élude pas mal le problème.

    L'exemple de jeha marche très bien et marchera en toute circonstances.

    L'ennui c'est qu'il faut partir des BigDecimal, calculer en BigDecimal et finir en BigDecimal, et que c'est chiant à manipuler ces bêtes-là, sans parler des performances si on en fait beaucoup.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Amont 9.999999999999998==10.0?false
    Amont 9.999999999999998==10.0?false
    Amont 9.999999999999998==10.0?true
    Amont 9.999999999999998==10.0?false
    Amont 9.999999999999998==10.0?false
    Amont 10.0000000000000==10.0?true
    Oui, enfin, pour ces raisons ou pour une autre, vérifier l'égalité des flottants, c'est pas fiable.
    C'est presque comme vérifier si deux nombres uniformément choisis au hasard entre 0 et 1 sont égaux. Par définition, ils ne peuvent pas l'être.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Effectivement, mon texte est ambigu. Big décimal utilise une virgule fixe et une base 10 oui, mais si tu lit mon message d'origine, le problème n'est pas la virgule, c'est la base (binaire). Hors bigdecimal, ben tu lui passe un double, donc le mal est déjà fait. Maintenant, j'ai pas testé, mais si tu remplace le code par



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
             BigDecimal bd = new BigDecimal("22.72").subtract(new BigDecimal("12.72"));
             result = bd.doubleValue()==10.0;
    c'est à dire en passant des String, là tu t'affranchis de la conversion Mais comme l'a dit jeha, il utilise déjà des double pour ses données, il est donc coincé de ce coté là.

  13. #13
    Membre confirmé
    Avatar de jeha
    Inscrit en
    Octobre 2005
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 127
    Par défaut
    Merci tout le monde pour vos messages et vos petites attentions!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 18/01/2010, 12h38
  2. Réponses: 5
    Dernier message: 29/05/2008, 10h05
  3. probléme dans une fonction qui retourne un data reader
    Par saraenim dans le forum Windows Forms
    Réponses: 32
    Dernier message: 28/04/2008, 21h53
  4. Réponses: 6
    Dernier message: 09/11/2007, 19h33
  5. Problème de nombre de ligne retournée
    Par dubidon dans le forum Langage SQL
    Réponses: 10
    Dernier message: 02/06/2007, 11h28

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