web-dev-qa-db-fra.com

Arrondir un double à 2 décimales

Si la valeur est 200.3456, elle doit être formatée en 200.34. S'il s'agit de 200, il devrait alors s'agir de 200.00.

430
Rajesh

Voici un utilitaire qui arrondit (au lieu de tronquant ) un double au nombre spécifié de décimales.

Par exemple:

round(200.3456, 2); // returns 200.35

Version originale; 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;
}

Ceci se décompose mal dans les cas où le nombre de décimales est très élevé (par exemple, round(1000.0d, 17)) ou une partie entière de grande taille (par exemple, round(90080070060.1d, 9)). Merci à Sloin pour l'avoir signalé.

J'utilise ce qui précède depuis des années pour arrondir les doublons "pas trop grands" à deux ou trois décimales (par exemple, pour nettoyer le temps en secondes à des fins de journalisation: 27.987654321987 -> 27.99). Mais je suppose qu'il est préférable de l'éviter, car des moyens plus fiables sont immédiatement disponibles, avec un code plus propre également.

Alors, utilisez ceci à la place

(Adapté de cette réponse de Louis Wasserman et celle de Sean Owen .)

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

    BigDecimal bd = BigDecimal.valueOf(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 RoundingMode , si vous pensez avoir besoin de quelque chose d’autre que Arrondi de banquiers .

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

Et dans tous les cas

Rappelez-vous toujours que les représentations à virgule flottante utilisant float et double sont inexactes . Par exemple, considérons ces expressions:

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

Pour être précis, vous voulez utiliser BigDecimal. Et pendant que vous y êtes, utilisez le constructeur qui prend une chaîne, jamais le 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")));

Quelques excellentes lectures complémentaires sur le sujet:


Si vous vouliez une mise en forme de type String au lieu de (ou en plus de) des nombres strictement arrondis, reportez-vous aux autres réponses.

En particulier, notez que round(200, 0) renvoie 200.0. Si vous voulez sortir " 200.00 ", commencez par tour, puis formatez le résultat pour le sortir (ce qui est parfaitement expliqué dans réponse de Jesper ).

744
Jonik

Si vous voulez simplement imprimer une double avec deux chiffres après le signe décimal, 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 utilisez la classe DecimalFormat:

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

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 cela va réellement arrondir pour vous, pas seulement le formatage.

114
Santiago

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

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

si val commence à 200.3456 puis passe à 20034.56, il est arrondi à 20035, puis on le divise pour obtenir 200,34.

si vous vouliez toujours arrondir, nous pourrions toujours tronquer en jetant un int:

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

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

67
luke

Veuillez utiliser Apache commons math :

Precision.round(10.4567, 2)
48
Pritesh Mhatre
function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

Notez le toString () !!!!

En effet, BigDecimal convertit la forme binaire exacte du double !!!

Ce sont les différentes méthodes suggérées et leurs 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 AGAIN - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - 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;
33
Luca Vix
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));
23
Abdullah AlHazmy
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
16
user1692711

Si vous voulez vraiment le même double, mais arrondi comme vous le souhaitez, vous pouvez utiliser BigDecimal, par exemple

new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
13
daoway

Arrondir un double n'est généralement pas ce que l'on veut. A la place, utilisez String.format() pour le représenter au format souhaité.

Pour deux chiffres arrondis. C'est très simple et vous mettez à jour la variable au lieu d'afficher uniquement ce que DecimalFormat fait.

x = Math.floor(x * 100) / 100;

7
Srujan Kumar Gulla

Dans votre question, il semble que vous souhaitiez éviter d’arrondir également les chiffres? Je pense que .format () arrondira les chiffres en deux, autant que je sache?
donc si vous voulez arrondir, 200.3456 devrait être 200.35 pour une précision de 2. Mais dans votre cas, si vous voulez juste les 2 premiers et ensuite écarter le reste?

Vous pouvez le multiplier par 100, puis lancer un int (ou prendre la parole du nombre), avant de diviser à nouveau par 100.

200.3456 * 100 = 20034.56;  
(int) 20034.56 = 20034;  
20034/100.0 = 200.34;

Cependant, vous pourriez avoir des problèmes avec de très gros nombres proches de la limite. Dans ce cas, la conversion en chaîne et en sous-chaîne fonctionnerait aussi facilement.

0
bryanallott
value = (int)(value * 100 + 0.5) / 100.0;
0
user2068610