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 :

Arrondi des nombres Double


Sujet :

avec Java

  1. #1
    Membre averti Avatar de clubist
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2008
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2008
    Messages : 217
    Points : 301
    Points
    301
    Par défaut Arrondi des nombres Double
    bonjour,

    la méthode Math.round() permet de faire round sur des double

    par exemple valeur initiale : 1.6 cette méthode retourne 2.0

    mais j'ai un cas ou la valeur est 1.856999

    je veux le rendre en 1.857 comment faire ça ?
    car la méthode round me donne 2.0 dans ce cas ?

    et merci d'avance.

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    Salut, tu peux utiliser les BidDecimal:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double a = 1.856999;
    BigDecimal bd = new BigDecimal(a);
    bd= bd.setScale(3,BigDecimal.ROUND_DOWN);
    a = bd.doubleValue();

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    281
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 281
    Points : 321
    Points
    321
    Par défaut
    Le truc classique est de multiplier par 10^3 , puis d'utiliser Math.round() et de rediviser par ((10^3)*1.0)

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    En fait, la "bonne méthode" dépend de ce qu'on veut en faire au juste :

    - si on veut continuer les calculs avec des nombres flottants approchés, mais qu'on veut arrondir cette valeur, la méthode "multiplier par 1000, utiliser Math.round() et diviser par 1000," est la bonne.

    - si on veut continuer des valeurs numériques, mais basés sur l'arrondi exact de ce flottant, il faut convertir le double en BigDecimal, arrondir le BigDecimal, et rester en BigDecimal. Les flottants sont approchés.Toujours.

    - Si on veut simplement afficher le nombre, ou le convertir en String en général, en arrondissant à la 3e décimale, il vaut mieux utiliser le DecimalFormat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    NumberFormat nf = new DecimalFormat("0.###");
    String s = nf.format(monNombre);
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    201
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Avril 2006
    Messages : 201
    Points : 75
    Points
    75
    Par défaut
    Bonjour,

    Toujours avec NumberFormat on a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    NumberFormat nf = new NumberFormat.getInstance();
    nf.setMaximumFractionDigits(3);
    String s = nf.format(monNombre);

  6. #6
    Membre actif
    Profil pro
    Développeur informatique
    Inscrit en
    Mars 2010
    Messages
    336
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2010
    Messages : 336
    Points : 227
    Points
    227
    Par défaut
    Salut,

    voici ma fonction pour arrondir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public double arrondir(double nombre,double nbApVirg)
    	{
    		return(double)((int)(nombre * Math.pow(10,nbApVirg) + .5)) / Math.pow(10,nbApVirg);
    	}
    Le premier paramètre est le nombre que tu souhaite arrondir et le second te permet de spécifier le nombre de chiffre après la virgule.

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2010
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2010
    Messages : 59
    Points : 86
    Points
    86
    Par défaut
    comme la fonction round, la fonction précédente présente un gros défaut!!!
    ATTENTION!!

    il y a parfois un problème quand il y a un zéro entre la virgule et le nombre de chiffre qu'on veut après la virgules:
    exemples avec la fonction précédente:
    arrondir(1.115,2) donne 1.12 correcte
    arrondir(1.015,2) donne 1.01 alors qu'il devrait donner 1.02
    arrondir(1.105,2) donne 1.11 correcte
    arrondir(1.005,2) donne 1.0 alors qu'il devrait donner 1.01

    pour les arrondies avec java, c'est dur sans passer par un substring et un traitement manuel.
    Cordialement,

    David.

  8. #8
    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,


    La solution a déjà été donnée !!!
    • Si on veut réellement arrondir la valeur, il faut passer le méthode setScale() de BigDecimal
    • Si on veut seulement arrondir lors de l'affichage, on peut utiliser la méthode setRoundingMode() du NumberFormat...



    a++

  9. #9
    Membre régulier
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2010
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2010
    Messages : 59
    Points : 86
    Points
    86
    Par défaut
    erf.. j'étais de passage pour signaler un bug que j'avais rencontrer et je me mange deux moins..

    bref je disais bien que les deux fonctions proposées plus haut avait un bug.. faite le test si vous êtes pas contents.. Mais c'est le cas, ça bug bien.

    après concernant le setscale du bigint j'arrive pas non plus a avoir le resultat désiré, mais je vais pas m'investir plus dedans vu que les intervenants ont l'air d'être satisfait.
    Cordialement,

    David.

  10. #10
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Citation Envoyé par davly Voir le message
    erf.. j'étais de passage pour signaler un bug que j'avais rencontrer et je me mange deux moins..

    bref je disais bien que les deux fonctions proposées plus haut avait un bug.. faite le test si vous êtes pas contents.. Mais c'est le cas, ça bug bien.
    Il n'y a pas de bug dans la méthode round(), elle fait précisément ce qu'elle doit faire.
    Ce que tu observes est dû à la nature même des double qui ne permettent pas de représenter un nombre précis, et donc, entre autres, ne peuvent prédire si l'approximation du chiffre que tu as demandé sera au-dessus ou en-dessous du 5 à la décimale voulue pile.

    Le bug, il est donc dans le fait d'utiliser des doubles alors qu'ils n'en sont pas capables. Raison pour laquelle on a indiqué grosso-modo trois cas de figure.

    Citation Envoyé par davly Voir le message
    après concernant le setscale du bigint j'arrive pas non plus a avoir le resultat désiré
    Je sais pas quoi te dire. Il y a un exemple en haut et il marche... Mais si tu pars d'un double, tu auras le même problème qu'avec les doubles, évidemment. Pareil avec NumberFormat.
    Si tu veux des nombres précis, commence et termine avec long ou BigDecimal, et ne touche jamais à double ou float. C'est comme ça que le calcul à virgule marche en informatique.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Candidat au Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2013
    Messages : 3
    Points : 3
    Points
    3
    Par défaut Réponse
    Salut,
    la discussion est assez lointaine, mais je partage néanmoins ma solution car j'ai tellement cherché solution face à ce problème mais j'ai rien trouvé.
    Bref voici ce que j'ai bidouillé!!
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    public static double round(double val, int pos){
     
    		if(((""+val).substring((""+val).indexOf('.')+1)).length()>pos+1){
    			int lastNumber = Integer.parseInt(""+(""+val).substring((""+val).indexOf('.')+pos+1, (""+val).indexOf('.')+pos+2));
    			double response = (double)((int) (val*Math.pow(10, pos+1)));
     
    	    	response = response / Math.pow(10, pos+1);
     
    	    	if(lastNumber >=5){
    	    		if(response>0){
    	    			response = response + 0.0001;
    	    		}else{
    	    			response = response - 0.0001;
    	    		}
     
    	    	   	response = (double)((int) (response*Math.pow(10, pos)));
    	    	   	response = response / Math.pow(10, pos);
    	    	}else{
    	        	response = (double)((int) (response*Math.pow(10, pos)));
    	        	response = response / Math.pow(10, pos);
    	    	}
     
    	    	return response;
    		}else{
     
    			return val;
    		}
        }
    J'espère que ça vous sera utile

  12. #12
    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
    Citation Envoyé par wilnzi Voir le message
    la discussion est assez lointaine, mais je partage néanmoins ma solution car j'ai tellement cherché solution face à ce problème mais j'ai rien trouvé.
    Pourtant tupac25 donne la réponse dans la première réponse de la discussion...



    Citation Envoyé par wilnzi Voir le message
    Bref voici ce que j'ai bidouillé!!
    Bidouillé c'est le mot !

    Déjà ta première condition fait que round(0.26,1) retourne 0.26. C'est normal ?

    Ensuite les multiples ""+val me font craindre le pire, puisque les doubles peuvent être affichés en valeur exponentielles...


    a++

  13. #13
    Membre averti Avatar de clubist
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2008
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2008
    Messages : 217
    Points : 301
    Points
    301
    Par défaut
    Bonjour et merci mes amis pour toutes vos réponses.

    Je vois que ce sujet est toujours cherché sur le net par plusieurs développeurs et c'est bien de partager des solution et des astuces pareils, j'ai ouvert ce sujet depuis plus de 5 ans et aujourd'hui j'ai eu un étudiant qui m'a demandé l'aide pour l'arrondissement, j'ai fais des recherches sur Google et je me suis tombé sur ma propre discussion c'est cool , sinon toutes les réponses sont utiles et surtout la première
    Citation Envoyé par tupac25 Voir le message
    Salut, tu peux utiliser les BidDecimal:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double a = 1.856999;
    BigDecimal bd = new BigDecimal(a);
    bd= bd.setScale(3,BigDecimal.ROUND_DOWN);
    a = bd.doubleValue();

  14. #14
    Membre actif Avatar de tnodev
    Profil pro
    SSSSS
    Inscrit en
    Mai 2005
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : SSSSS

    Informations forums :
    Inscription : Mai 2005
    Messages : 182
    Points : 231
    Points
    231
    Par défaut
    Bonjour,

    quelques années après, je me permets d'ajouter une information importante :

    Attention
    Si notre double = 61.785 alors le new BigDecimal(double) = 61.784999999999996589394868351519107818603515625

    Il me semble qu'il vaut mieux faire un new BigDecimal(double.toString()) = 61.785

    TNO

  15. #15
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Hello,

    Citation Envoyé par tnodev Voir le message
    Si notre double = 61.785 alors le new BigDecimal(double) = 61.784999999999996589394868351519107818603515625
    ça n'existe pas, un double de valeur 61.785. Les double ne sont pas capables de représenter cette valeur.

    Si tu écris le code suivant:

    Tu indiques que tu souhaites que la variable d contienne la valeur double la plus proche existante du nombre décimal 61.785.
    Et il se trouve que cette valeur la plus proche qu'on puisse mettre dans un double, c'est 61.784999999999996589394868351519107818603515625.
    le constructeur BigDecimal(double) a donc bien fonctionné.

    Si on veut une valeur précise, il faut faire new BigDecimal("61.785") (c'est un littéral String, pas nombre.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 13/10/2008, 12h20
  2. Réponses: 1
    Dernier message: 21/04/2008, 17h00
  3. Réponses: 3
    Dernier message: 22/05/2005, 13h59
  4. [LG]Extraire des nombres d'une chaine
    Par audreym31 dans le forum Langage
    Réponses: 4
    Dernier message: 18/01/2004, 22h24
  5. Réponses: 3
    Dernier message: 08/09/2003, 16h06

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