456 votes

Arrondir un double à 2 décimales

Supposons que si la valeur est 200.3456, elle doit être formatée en 200.34 ou si elle est 200, elle doit être 200.00.

779voto

Jonik Points 18905

Voici un utilitaire qui rondes (au lieu de tronqué ) un double avec le nombre de décimales spécifié.

Par exemple :

round(200.3456, 2); // returns 200.35

Version originale ; faites attention avec ça

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    long factor = (long) Math.pow(10, places);
    value = value * factor;
    long tmp = Math.round(value);
    return (double) tmp / factor;
}

Este tombe en panne dans les cas particuliers, avec un nombre très élevé de décimales (par exemple, le nombre d'heures de travail). round(1000.0d, 17) ) ou une grande partie d'un nombre entier (par ex. round(90080070060.1d, 9) ). Merci à Sloin pour avoir souligné ce point.

J'ai utilisé la méthode ci-dessus pour arrondir des doubles "pas trop gros" à 2 ou 3 décimales avec bonheur pendant des années (par exemple pour nettoyer le temps en secondes à des fins de journalisation : 27.987654321987 -> 27.99). Mais je pense qu'il vaut mieux l'éviter, puisque des méthodes plus fiables sont facilement disponibles, avec un code plus propre également.

Alors, utilisez ceci à la place

(Adapté de cette réponse de Louis Wasserman y celui-ci par Sean Owen .)

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

Notez que HALF_UP est le mode d'arrondi "couramment enseigné à l'école". Parcourez le Documentation sur le RoundingMode si vous pensez avoir besoin d'autre chose.

Bien sûr, si vous préférez, vous pouvez mettre en ligne ce qui précède dans une seule ligne :
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

Et dans tous les cas

N'oubliez jamais que les représentations en virgule flottante utilisant float y double sont inexact . Par exemple, considérez ces expressions :

999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001

Pour plus de précision, il est préférable d'utiliser BigDecimal. . Et tant qu'à faire, utilisez le constructeur qui prend un String, jamais celui qui prend un double. Par exemple, essayez d'exécuter ceci :

System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));

D'excellentes lectures complémentaires sur le sujet :


Si tu voulais que String mise en forme au lieu (ou en plus) d'arrondir strictement les chiffres, voir les autres réponses.

Plus précisément, notez que round(200, 0) renvoie à 200.0 . Si vous voulez produire " 200.00 ", vous devez d'abord arrondir et ensuite formater le résultat pour la sortie (ce qui est parfaitement expliqué dans La réponse de Jesper ).

325voto

Jesper Points 65733

Si vous voulez juste imprimer un double avec deux chiffres après la virgule, utilisez quelque chose comme ceci :

double value = 200.3456;
System.out.printf("Value: %.2f", value);

Si vous voulez avoir le résultat dans un String au lieu d'être imprimé sur la console, utilisez String.format() avec les mêmes arguments :

String result = String.format("%.2f", value);

Ou utiliser la classe DecimalFormat :

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));

122voto

Santiago Points 391

Je pense que c'est plus facile :

double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(time));

System.out.println(time); // 200.35

Notez que cette fonction permet d'arrondir les chiffres, et pas seulement de les formater.

69voto

luke Points 6688

Le moyen le plus simple serait de faire un tour comme ceci ;

double val = ....;
val = val*100;
val = Math.Round(val);
val = val /100;

Si la valeur commence à 200.3456, elle va jusqu'à 20034.56, puis elle est arrondie à 20035, puis nous la divisons pour obtenir 200.34.

si l'on voulait toujours arrondir à l'inférieur, on pourrait toujours tronquer en coulant vers un int :

double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;

Cette technique fonctionnera dans la plupart des cas, car pour les très grands doubles (positifs ou négatifs), elle peut déborder. Mais si vous savez que vos valeurs seront dans une plage appropriée, cela devrait fonctionner pour vous.

38voto

Luca Vix Points 21
function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

Notez le toString() !!!!

C'est parce que BigDecimal convertit la forme binaire exacte du double !!!

Il s'agit des différentes méthodes proposées et de leur cas d'échec.

// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue() 

Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAING - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OPS - new DecimalFormat("0.00").format(val) 
// By default use half even, works if you change mode to half_up 

Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X