Java BigDecimal: En yakın tam değere yuvarlayın


91

Aşağıdaki sonuçlara ihtiyacım var

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

.round()veya .setScale()? Bunu nasıl yapacağım?

Yanıtlar:


156

setScale()Kesirli basamakların sayısını sıfıra indirmek için kullanabilirsiniz . valueYuvarlanacak değeri tuttuğunu varsayarsak :

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

Saklanacak round()basamak sayısını belirtmenizi gerektirdiğinden kullanmak biraz daha karmaşıktır. Örneklerinizde bu 3 olabilir, ancak bu tüm değerler için geçerli değildir:

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

( BigDecimalNesnelerin değişmez olduğunu setScaleve roundher ikisinin de yeni bir nesne döndüreceğini unutmayın.)


1
Çalışmıyor: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75
Boris Pavlović

3
Hayır, ölçeği ayarlamak, ilkiyle aynı olmayan yeni bir ondalık döndürür. Örneğin: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));yanlış yazdırır
Daniel Fath

6
@Daniel: Cevabımda yayınladığım kod pasajında ​​zaten ima edilmişti. Şimdi bunu açık hale getirdim.
Grodriguez

RoundingModeo nedir? Bu varBigDecimal
üçleme


10

Grodriguez'in cevabına göre gidersem

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

Bu çıktı

100.23 -> 100
100.77 -> 101

İstediğim tam olarak bu değil, bu yüzden bunu yaptım ..

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

Bu benim aldığım

100.23 -> 100.00
100.77 -> 101.00

Bu benim sorunumu şimdilik çözüyor ..:) Hepinize teşekkür ederim.


7
İlk sonucun "istediğim gibi olmadığı" ifadesini merak ediyorum. Çıktı biçimlendirmesi konusunda gerçekten endişeleriniz varsa , bir geri dönüşün dizeye dönüştürülmesini yönetmek için DecimalFormat(olduğu gibi new DecimalFormat("###.00")) kullanabilirsiniz BigDecimal. Sonuç "101.00"olarak, hem @Grodriquez'den hem de sizin oluşturduğunuz parçacıkların değerini verir .
joel .neely

3
Zaten bir tamsayınız olduğunu bildiğiniz için burada ikinci kez yuvarlamak gereksizdir, bu yüzden onun yerine BigDecimal.ROUND_UNNECESSARY'yi kullanırdım, bence biraz daha net.
kosmoplan

5

İşte son derece karmaşık bir çözüm, ancak işe yarıyor:

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

Test Kodu:

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

Çıktı:

100
100
101
101


Bu çözümü ya da herhangi bir şeyi desteklememek, ancak input.toBigInteger().toString().length()bir logaritma kullanarak parça çok daha verimli olurdu, bir şeyround_up(log(input)) + (1 if input is a power of ten, else 0)
Addison


0

Tek bir komutla bunu tamamlayabileceğinizi sanmıyorum. Deneyin

    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

Örneklerinizin geri kalanı için test ettim ve istenen değerleri döndürüyor, ancak doğruluğunu garanti etmiyorum.


-2

İstediğiniz

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

2
Bu hiçbir şey yapmaz. Şu dokümantasyondan round: "Hassaslık ayarı 0 ise yuvarlama yapılmaz."
Grodriguez
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.