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

avec Java Discussion :

Problème de multiplication et arrondis


Sujet :

avec Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 40
    Points : 30
    Points
    30
    Par défaut Problème de multiplication et arrondis
    Bonjour,

    J'ai un problème dans une multiplication de 2 doubles en Java. Il ne me calcul pas le bon résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    double d1 = 663.75;
    double d2 = 1.196;
    System.out.println(d1*d2);
    Renvoie : 793.8449999999999 au lieu de 793.845

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    java.math.BigDecimal bg = new java.math.BigDecimal(663.75d);
    java.math.BigDecimal bg2 = new java.math.BigDecimal(1.196d);
    System.out.println(bg.multiply(bg2));
    Renvoie : 793.844999999999968165464991898261359892785549163818359375

    Pourquoi cela, et comment avoir un bon chiffre ? J'ai pensé à ajouter 0.0000001 mais je trouve cela bizarre qu'il ne soit pas capable de calculer juste au dela de 3 pauvres décimales.

    Environnement : Windows, JDK 1.5.0_15, TomCat 5.5

    Merci pour votre aide.

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 40
    Points : 30
    Points
    30
    Par défaut
    La réponse pour ceux qui auraient le même problème :

    Utiliser le constructeur String de BigDecimal, et pas le double !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    double d1 = 663.75;
    double d2 = 1.196;
    BigDecimal bg1 = new BigDecimal("" + d1);
    BigDecimal bg2 = new BigDecimal("" + d2);
    System.out.printlnt(bg1.multiply(bg2).doubleValue());
    renvoie 793.84500

  3. #3
    Membre éclairé
    Homme Profil pro
    NoOb
    Inscrit en
    Mai 2007
    Messages
    554
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : NoOb

    Informations forums :
    Inscription : Mai 2007
    Messages : 554
    Points : 852
    Points
    852
    Par défaut
    Bonjour,

    Ceci fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    double d1 = 663.75;
    double d2 = 1.196;
    System.out.println((float) (d1*d2));

  4. #4
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 074
    Points : 7 978
    Points
    7 978
    Par défaut
    En utilisant les simple type (float, double), tu devras arrondir tes resultats quand tu affichage (ou durant le calcul si necessaire).

    En utilisante BigDecimal tu ne dois pas utiliser BigDecimal(123.0d) mais BigDecimal("123.0"); sinon tu auras les meme erreurs.

    EDIT : Grillé
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par Ougha Voir le message
    Pourquoi cela, et comment avoir un bon chiffre ?
    Les nombres à virgules flottantes sont des approximations qui peuvent entrainer des erreurs d'arrondis...
    Certaines valeurs ne peuvent pas être représenté de manière précise et amènes des approximations plus ou moins grande...

    Citation Envoyé par Ougha Voir le message
    J'ai pensé à ajouter 0.0000001 mais je trouve cela bizarre qu'il ne soit pas capable de calculer juste au dela de 3 pauvres décimales.
    Les approximations surviennent en général après la 18ième décimales, et l'affichage par défaut fait un arrondi pour éviter de représenter cette approximation. Le problème c'est qu'avec les calculs ces approximations peuvent s'amplifier et remonter dans les décimales si bien qu'on les aperçoit à l'écran (comme dans ton cas)

    Le calcul est bon à 10 décimales environs il me semble... Mais l'affichage par défaut en utilise bien plus :
    [code] double d1 = 663.75;
    double d2 = 1.196;
    System.out.printf("%.10f%n", d1*d2); // arrondi à 10 décimales[/quote]


    Quand aux BigDecimal, ils permettent des calcul de précision, mais uniquement lorsqu'il sont utilisé avec des valeurs correctes : il faut les initialiser avec des String et non pas des doubles, sinon tu conserves l'approximation !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    new BigDecimal(663.75d); // 663.75
    new BigDecimal(1.196d); // 1.1959999999999999520383653361932374536991119384765625


    Après tout dépend de ton besoin de précision. Pour des calculs simple tu peux très bien utiliser des doubles si tu n'as pas besoin de beaucoup de décimales... quitte à arrondir le résultat de temps en temps pour éviter de trop amplifier l'approximation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	public static double round(double value, int decimal) {
    		// On transforme en un BigDecimal (avec l'approximation donc).
    		BigDecimal bd = new BigDecimal(value);
    		// On arrondi au nombre de décimales :
    		bd = bd.setScale(decimal, BigDecimal.ROUND_HALF_UP);
    		// Que l'on retransforme en double :
    		return bd.doubleValue();
    	}

    a++


    [edit] Genoce : ton cast en float est un coup de chance ! Tu risques au contraire d'amplifier l'approximation !

  6. #6
    Membre éclairé
    Homme Profil pro
    NoOb
    Inscrit en
    Mai 2007
    Messages
    554
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : NoOb

    Informations forums :
    Inscription : Mai 2007
    Messages : 554
    Points : 852
    Points
    852
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    [edit] Genoce : ton cast en float est un coup de chance ! Tu risques au contraire d'amplifier l'approximation !
    C'est noté

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

Discussions similaires

  1. Problème definitions multiple (Makefile?)
    Par zuzuu dans le forum Systèmes de compilation
    Réponses: 2
    Dernier message: 07/12/2006, 14h18
  2. probléme : template multiple et héritage simple.
    Par laetmo dans le forum Langage
    Réponses: 1
    Dernier message: 03/08/2006, 02h44
  3. problème requete multiplication
    Par MichMich29 dans le forum Langage SQL
    Réponses: 28
    Dernier message: 24/05/2006, 10h16
  4. [FLASH MX] Problème onPress multiple
    Par abenhass dans le forum ActionScript 1 & ActionScript 2
    Réponses: 3
    Dernier message: 14/04/2006, 09h25
  5. [KeyEvent] Problème de multiples appels
    Par pierre.zelb dans le forum AWT/Swing
    Réponses: 13
    Dernier message: 11/08/2005, 14h53

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