Java BigDecimal: arrondir à la valeur entière la plus proche


89

J'ai besoin des résultats suivants

100.12 -> 100.00
100.44 -> 100.00
100.50 -> 101.00
100.75 -> 101.00

.round()ou .setScale()? Comment dois-je procéder?

Réponses:


151

Vous pouvez utiliser setScale()pour réduire le nombre de chiffres fractionnaires à zéro. En supposant que valuela valeur doit être arrondie:

BigDecimal scaled = value.setScale(0, RoundingMode.HALF_UP);
System.out.println(value + " -> " + scaled);

L'utilisation round()est un peu plus compliquée car elle vous oblige à spécifier le nombre de chiffres à conserver. Dans vos exemples, ce serait 3, mais ce n'est pas valable pour toutes les valeurs:

BigDecimal rounded = value.round(new MathContext(3, RoundingMode.HALF_UP));
System.out.println(value + " -> " + rounded);

(Notez que les BigDecimalobjets sont immuables; les deux setScaleet roundrenverront un nouvel objet.)


1
Cela ne fonctionne pas: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75
Boris Pavlović

3
Non, la définition de l'échelle renvoie une nouvelle décimale différente de la première. Par exemple: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));imprime faux
Daniel Fath

6
@Daniel: C'était déjà sous-entendu dans l'extrait de code que j'ai posté dans ma réponse. Je l'ai maintenant rendu explicite.
Grodriguez

RoundingModeQu'est-ce que c'est? C'estBigDecimal
trilogie


10

Si je passe par la réponse de Grodriguez

System.out.println("" + value);
value = value.setScale(0, BigDecimal.ROUND_HALF_UP);
System.out.println("" + value);

C'est la sortie

100.23 -> 100
100.77 -> 101

Ce n'est pas tout à fait ce que je veux, alors j'ai fini par faire ça ...

System.out.println("" + value);
value = value.setScale(0, BigDecimal.ROUND_HALF_UP);
value = value.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("" + value);

C'est ce que je reçois

100.23 -> 100.00
100.77 -> 101.00

Cela résout mon problème pour l'instant ..:) Merci à tous.


7
Je suis curieux de savoir que le premier résultat "n'est pas tout à fait ce que je veux ...". Si vous êtes réellement préoccupé par le formatage de sortie, vous pouvez utiliser DecimalFormat(comme dans new DecimalFormat("###.00")) pour gérer la conversion d'un BigDecimalretour en chaîne. Il donne "101.00"comme résultat pour les deux valeurs que les extraits de @Grodriquez et que vous avez créés.
joel.neely

3
La deuxième fois que vous arrondissez ici n'est pas nécessaire car vous savez que vous avez déjà un entier, donc j'utiliserais BigDecimal.ROUND_UNNECESSARY à la place, un peu plus clair à mon avis.
kosmoplan

5

Voici une solution terriblement compliquée, mais cela fonctionne:

public static BigDecimal roundBigDecimal(final BigDecimal input){
    return input.round(
        new MathContext(
            input.toBigInteger().toString().length(),
            RoundingMode.HALF_UP
        )
    );
}

Code de test:

List<BigDecimal> bigDecimals =
    Arrays.asList(new BigDecimal("100.12"),
        new BigDecimal("100.44"),
        new BigDecimal("100.50"),
        new BigDecimal("100.75"));
for(final BigDecimal bd : bigDecimals){
    System.out.println(roundBigDecimal(bd).toPlainString());
}

Production:

100
100
101
101


Ne pas approuver cette solution ou quoi que ce soit, mais la input.toBigInteger().toString().length()partie serait beaucoup plus efficace en utilisant un logarithme, quelque chose commeround_up(log(input)) + (1 if input is a power of ten, else 0)
Addison


0

Je ne pense pas que vous puissiez l'arrondir comme ça en une seule commande. Essayer

    ArrayList<BigDecimal> list = new ArrayList<BigDecimal>();
    list.add(new BigDecimal("100.12"));
    list.add(new BigDecimal("100.44"));
    list.add(new BigDecimal("100.50"));
    list.add(new BigDecimal("100.75"));

    for (BigDecimal bd : list){
        System.out.println(bd+" -> "+bd.setScale(0,RoundingMode.HALF_UP).setScale(2));
    }

Output:
100.12 -> 100.00
100.44 -> 100.00
100.50 -> 101.00
100.75 -> 101.00

J'ai testé pour le reste de vos exemples et il renvoie les valeurs voulues, mais je ne garantis pas son exactitude.


-2

Tu veux

round(new MathContext(0));  // or perhaps another math context with rounding mode HALF_UP

2
Cela ne fait rien. D'après la documentation de round: "Si le paramètre de précision est égal à 0, aucun arrondi n'a lieu."
Grodriguez
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.