Java BigDecimal: Auf den nächsten ganzen Wert runden

88

Ich brauche die folgenden Ergebnisse

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

.round()oder .setScale()? Wie gehe ich vor?

n / a
quelle

Antworten:

150

Mit können Sie setScale()die Anzahl der Bruchstellen auf Null reduzieren. Angenommen, der zu valuerundende Wert enthält:

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

Die Verwendung round()ist etwas komplizierter, da Sie die Anzahl der beizubehaltenden Ziffern angeben müssen. In Ihren Beispielen wäre dies 3, dies gilt jedoch nicht für alle Werte:

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

(Beachten Sie, dass BigDecimalObjekte sind unveränderlich, beide setScaleund roundein neues Objekt zurück.)

Grodriguez
quelle
1
Es funktioniert nicht: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75
Boris Pavlović
3
Nein, beim Einstellen der Skalierung wird eine neue Dezimalstelle zurückgegeben, die nicht mit der ersten identisch ist. Zum Beispiel: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));druckt falsch
Daniel Fath
6
@ Daniel: Das war bereits in dem Code-Snippet enthalten, das ich in meiner Antwort gepostet habe. Ich habe es jetzt explizit gemacht.
Grodriguez
RoundingModewas ist das? Es istBigDecimal
Trilogie
10

Wenn ich mich an Grodriguez 'Antwort halte

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

Dies ist die Ausgabe

100.23 -> 100
100.77 -> 101

Was nicht ganz das ist, was ich will, also habe ich das gemacht.

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

Das bekomme ich

100.23 -> 100.00
100.77 -> 101.00

Dies löst mein Problem vorerst .. :) Vielen Dank an alle.

n / a
quelle
7
Ich bin gespannt auf die Aussage, dass das erste Ergebnis "nicht ganz das ist, was ich will ...". Wenn Sie sich tatsächlich Gedanken über die Ausgabeformatierung machen, können Sie DecimalFormat(wie in new DecimalFormat("###.00")) die Konvertierung eines BigDecimalBacks in einen String verwalten. Es ergibt "101.00"als Ergebnis für beide Werte, dass die Snippets von @Grodriquez und Sie erstellt haben.
joel.neely
3
Das zweite Mal, wenn Sie hier runden, ist unnötig, da Sie wissen, dass Sie bereits eine Ganzzahl haben. Daher würde ich stattdessen BigDecimal.ROUND_UNNECESSARY verwenden, was meiner Meinung nach etwas klarer ist.
Kosmoplan
5

Hier ist eine schrecklich komplizierte Lösung, aber sie funktioniert:

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

Testcode:

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());
}

Ausgabe:

100
100
101
101

Sean Patrick Floyd
quelle
Nicht um diese Lösung oder irgendetwas zu unterstützen, aber der input.toBigInteger().toString().length()Teil wäre viel effizienter, wenn ein Logarithmus verwendet würde, so etwas wieround_up(log(input)) + (1 if input is a power of ten, else 0)
Addison
0

Ich glaube nicht, dass Sie es mit einem einzigen Befehl so abrunden können. Versuchen

    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

Ich habe den Rest Ihrer Beispiele getestet und es werden die gewünschten Werte zurückgegeben, aber ich kann die Richtigkeit nicht garantieren.

Daniel Fath
quelle
-2

Sie wollen

round(new MathContext(0));  // or perhaps another math context with rounding mode HALF_UP
Jacobm
quelle
2
Das macht nichts. Aus der Dokumentation von round: "Wenn die Genauigkeitseinstellung 0 ist, findet keine Rundung statt."
Grodriguez