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

Java Discussion :

[Math]problème multiplication double


Sujet :

Java

  1. #1
    xso
    xso est déconnecté
    Futur Membre du Club
    Inscrit en
    Juillet 2003
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 11
    Points : 7
    Points
    7
    Par défaut [Math]problème multiplication double
    Voici un bout de code tout simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    double a = 0.815;
    double b = 26130.3;
    double c = a * b;
    System.err.println(c);
    J'obtiens le résultat suivant : 21296.194499999998 au lieu de 21296.1945.

    Quelqu'un aurait-il une solution pour résoudre ce problème sans passer par les BigDecimal et sans utiliser une précision qui pourrait introduire une erreur dans mes calculs?

  2. #2
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    C'est la précision éternelle de java....

    Je pense que tu peux regarder dans le package java.math (que je n'ai jamais essayé).

    Il y a les classes BigInteger et BigDecimal.

    Dans BigDecimal tu as une méthode multiply.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import java.math.BigDecimal;
     
    public class Multiplication
    {
    	public static void main (String [] telsArgs)
    	{
    		BigDecimal monBigDecimal1 = 0.815;
    		BigDecimal monBigDecimal2 = 26130.3;
    		BigDecimal monBigDecimal3 = monBigDecimal1.multiply(monBigDecimal2);
    		System.out.println(monBigDecimal3.toString());
    	}//main()
    }//class Multiplication

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 42
    Points : 37
    Points
    37
    Par défaut
    Sinon, tu peux toujours passer par une méthode d'arrondi à x chiffres aprés la virgule.

    Ou encore, ne faire que des multiplications sur des entiers. C'est plus sur

    Dans ton cas, tu multiplie tout par 1000 et tu redivises le résultat par 1000 à la fin ...

  4. #4
    Membre chevronné
    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
    Points : 1 996
    Points
    1 996
    Par défaut
    Ce sujet a déjà été traité cette semaine (addition de double)
    Bien le bonjour chez vous
    Jowo

  5. #5
    xso
    xso est déconnecté
    Futur Membre du Club
    Inscrit en
    Juillet 2003
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    J'ai cherché sur le forum avant de poster mon message, mais j'ai cherché à "multiplication double" et pas à "addition double"...

    Pour les BigDecimal, ça marche pas non plus car j'obtiens :
    21296.19449999999801450734082663988613836786099092128303478244077950876089744269847869873046875
    donc c'est toujours pas ce que je veux...

    Quand à arrondir la valeur, ça me fait perdre de la précision, parce que dans cet exemple, je peux arrondir à 4 chiffres après la virgule, mais dans un autre cas ça peut être 5 ou 6 (voir plus) chiffres après la virgule...

    Bon en tout cas merci pour vos réponses.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 42
    Points : 37
    Points
    37
    Par défaut
    Ca depend de quoi ton nombre de chiffres aprés la virgule ?

  7. #7
    xso
    xso est déconnecté
    Futur Membre du Club
    Inscrit en
    Juillet 2003
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    le nombre de chiffres après la virgule ne dépend pas de moi, ça s'est sur
    Ce sont des données extraites d'un fichier xml (que l'on me fournit...).

    Pour en revenir au sujet déjà traité cette semaine, je tiens quand même à préciser qu'aucune solution n'a été trouvée, donc le sujet reste ouvert...

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 42
    Points : 37
    Points
    37
    Par défaut
    Tu peux assez facilement retrouver le nombre de chiffres après la virgule pour un double donnée. Tu convertie en String et tu comptes le nombre de caractères de la virgule (ou du point) jusqu'à la fin.

    Après, tu peux tout multiplier par 10 x le nombre de chiffres après la virgule,
    faire la multiplication des 2 entiers (des long) et rediviser par 10 x le nombre de chiffres après la virgule

    Ca reste une solution possible et sûr

  9. #9
    Membre chevronné
    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
    Points : 1 996
    Points
    1 996
    Par défaut
    Citation Envoyé par xso
    J'ai cherché sur le forum avant de poster mon message, mais j'ai cherché à "multiplication double" et pas à "addition double"...

    Pour les BigDecimal, ça marche pas non plus car j'obtiens :
    21296.19449999999801450734082663988613836786099092128303478244077950876089744269847869873046875
    donc c'est toujours pas ce que je veux...

    Quand à arrondir la valeur, ça me fait perdre de la précision, parce que dans cet exemple, je peux arrondir à 4 chiffres après la virgule, mais dans un autre cas ça peut être 5 ou 6 (voir plus) chiffres après la virgule...

    Bon en tout cas merci pour vos réponses.
    MOI, j'obtiens 21296.1945 en utilisant correctement la classe BigDecimal.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        BigDecimal monBigDecimal1 = new BigDecimal(0.815d);
        BigDecimal monBigDecimal2 = new BigDecimal(26130.3d);
        BigDecimal monBigDecimal3 = monBigDecimal1.multiply(monBigDecimal2);
        System.out.println(monBigDecimal3.setScale(4, BigDecimal.ROUND_CEILING));
    Bien le bonjour chez vous
    Jowo

  10. #10
    xso
    xso est déconnecté
    Futur Membre du Club
    Inscrit en
    Juillet 2003
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Bé tu fais un arrondi à la quatrième décimale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        System.out.println(monBigDecimal3.setScale(4, BigDecimal.ROUND_CEILING));
    Ducoup je vois pas l'interêt de passer par des BigDecimal...
    :

    Pour ce qui est de la solution de compter le nombre de décimal en passant par des String, j'ai peur de perdre énormént de perfomance sur mon appli parce que j'ai pas qu'une seule valeur à analyser, non?

  11. #11
    Membre chevronné
    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
    Points : 1 996
    Points
    1 996
    Par défaut
    De toute façon, tu devras arrondir pour afficher ton nombre.

    Je peux me tromper mais un nombre avec 30 décimals, ça n'a pas de sens physique. Tout instrument a une certaine précision...
    Bien le bonjour chez vous
    Jowo

  12. #12
    xso
    xso est déconnecté
    Futur Membre du Club
    Inscrit en
    Juillet 2003
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    En effet, je vais me résoudre à arrondir mes résultats à la douzième décimale...

    Mais je trouve quand même étrange que Java ne permette pas de faire un calcul aussi simple que 0.815 * 26130.3 sans se tromper...

    Merci Jowo et Sebounet19 pour votre aide et votre patience ;-)

  13. #13
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    Java n'est pas vraiment fait pour le calcul, je pense que tu peux ajouter des librairies spécialisées qui te rendent un meilleur résultat.

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 106
    Points : 130
    Points
    130
    Par défaut
    c'est pas une question de qualité de calcul c'est une question de gestion mémoire.
    La JVM alloue 64 bits pour un double...Il faut bien les remplir.
    Passes par un float qui lui est codé sur 32 bits.

    Tu auras une précision plus grossière.

    Tchou !
    PHP / J2EE

  15. #15
    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
    'soir,

    Pour en revenir au sujet déjà traité cette semaine, je tiens quand même à préciser qu'aucune solution n'a été trouvée, donc le sujet reste ouvert...
    En fait, aucune solution n'a été trouvé parce qu'il n'en existe pas.

    A priori, il n'est pas possible de représenter certaines valeurs décimales avec des types primitifs (double, float, etc...) sans avoir recours à une approximation.

    Du coup, lors de certains calculs, les résultats peuvent être mathématiquement faux et être pourtant ce qu'il y a de plus proche avec une représentation informatique.

    De la même manière, (cf. un expert Java de ma boite), la valeur affichée par un System.out ne correspond pas toujours à la valeur exact retenue en mémoire. Par exemple :
    BigDecimal

    public BigDecimal(double val)

    Translates a double into a BigDecimal. The scale of the BigDecimal is the smallest value such that (10scale * val) is an integer.

    Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances notwithstanding.

    The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal(".1") is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.

    Parameters:
    val - double value to be converted to BigDecimal.
    Throws:
    NumberFormatException - val if val is infinite or NaN.
    Voir : http://java.sun.com/j2se/1.4.2/docs/api/

    Voilà tout...
    "Ils ne savaient pas que c'était impossible... alors ils l'ont fait." Mark Twain

  16. #16
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 845
    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 845
    Points : 22 850
    Points
    22 850
    Billets dans le blog
    51
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Java n'est pas vraiment fait pour le calcul, je pense que tu peux ajouter des librairies spécialisées qui te rendent un meilleur résultat.
    Je soupconne un probleme equivalent en C, C++, Pascal, ... et n'importe quel language qui utilise la norme IEEE ou equivalent pour la representation et les calculs sur nombres flottants (l'assembleur egalement alors ?).
    Mais de la a tous se mettre a programmer en FORTRAN, en Scheme/LISP ou en ML.........................

    Sinon il faut trouver (ou se faire) une librairie numerique specialisee. Mais la on peut alors perdre en performances et en general ca coute cher.
    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

  17. #17
    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
    d'accord avec bouye !

    D'une façon générale si tu n'obtiens pas le résultat attendu par ton ordi ben c que tu lui dis pas de faire les choses correctement (et c pas facile) !
    La manipulation des doubles (cf le poste sur l'addition de double) est très délicate, on utilises cette précision pour des calculs scientifiques (pas pour aditionner des sous ou des carottes !)
    Un nombre double ne s'écrit pas n'importe comment non plus, par exemple en info il se peut très bien que ces deux doubles ne soient pas égaux :
    d1=8.1
    d2=8.1000

    Bref en gros si tu n'as pas à déterminer l'âge de l'univers ou résoudre l'équation de schrödinger (donc t'as pas besoin d'être très précis) n'utilise pas les double (en plus ton appli ira sûrement plus vite !) !

    Si par contre tu dois résoudre une équation par différences finies en mode implicite allant au 5ème ordre, bon là tu peux envisager les doubles et un conseil avant d'écrire koi que ce soit c'est de lire des bouquins sur "les méthodes numériques" ou informatique numérique...

  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
    La manipulation des doubles (cf le poste sur l'addition de double) est très délicate, on utilises cette précision pour des calculs scientifiques (pas pour aditionner des sous ou des carottes !) ....
    Bref en gros si tu n'as pas à déterminer l'âge de l'univers ou résoudre l'équation de schrödinger (donc t'as pas besoin d'être très précis) n'utilise pas les double (en plus ton appli ira sûrement plus vite !) !
    Oulala... Fouilhouilhou...
    Mais pas du tout!!!

    Les deux postes sur les doubles montrent justement les limites de ce type primitif. Ils ne permettent pas de représenter PRECISEMENT certaines valeurs. Donc pas question de les utiliser dans des calculs nécessitant une extrême précision.
    "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
    Citation Envoyé par vincent63
    La manipulation des doubles (cf le poste sur l'addition de double) est très délicate, on utilises cette précision pour des calculs scientifiques (pas pour aditionner des sous ou des carottes !) ....
    Bref en gros si tu n'as pas à déterminer l'âge de l'univers ou résoudre l'équation de schrödinger (donc t'as pas besoin d'être très précis) n'utilise pas les double (en plus ton appli ira sûrement plus vite !) !
    Oulala... Fouilhouilhou...
    Mais pas du tout!!!

    Les deux postes sur les doubles montrent justement les limites de ce type primitif. Ils ne permettent pas de représenter PRECISEMENT certaines valeurs. Donc pas question de les utiliser dans des calculs nécessitant une extrême précision.
    ben ils servent à quoi alors ?? C'est bien avec ceux ci que tu peux avoir des 10E-350 ou 10E+241... non pour toi c'est pas assez précis ?? Un double ça s'écrit de façon précise dans un programme : 1.200000000000000 s'il le faut.

  20. #20
    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
    ben ils servent à quoi alors ?? C'est bien avec ceux ci que tu peux avoir des 10E-350 ou 10E+241... non pour toi c'est pas assez précis ?? Un double ça s'écrit de façon précise dans un programme : 1.200000000000000 s'il le faut.
    Je te renvoie à la page précédente et sur le lien vers la java doc. Toutes les valeurs ne peuvent pas être représentées EXACTEMENT avec les doubles. Par exemple, 0,1 n'a pas de représentation PRECISE avec ce type primitif.

    Pour des calculs qui demandent une grande précision, un léger décalage multiplié plusieurs fois peut donner des valeurs fausses.
    "Ils ne savaient pas que c'était impossible... alors ils l'ont fait." Mark Twain

Discussions similaires

  1. [AC-2007] Champ multiple double
    Par polemos dans le forum Modélisation
    Réponses: 2
    Dernier message: 15/04/2010, 10h52
  2. Problème de multiplication double/int
    Par gmirasaad dans le forum Langage
    Réponses: 2
    Dernier message: 27/05/2009, 14h13
  3. [Symbolic Math Toolbox ] sym et double
    Par jbollagnier dans le forum MATLAB
    Réponses: 10
    Dernier message: 27/07/2007, 15h22
  4. Réponses: 9
    Dernier message: 22/06/2006, 10h11
  5. Multiples double combobox indépendantes entre elles ??
    Par exway01 dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 08/03/2006, 09h34

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