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?

n / a
la source

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.)

Grodriguez
la source
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.

n / a
la source
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

Sean Patrick Floyd
la source
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.

Daniel Fath
la source
-2

Tu veux

round(new MathContext(0));  // or perhaps another math context with rounding mode HALF_UP
Jacobm
la source
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