Java BigDecimal: ปัดเศษเป็นค่าทั้งหมดที่ใกล้เคียงที่สุด


91

ฉันต้องการผลลัพธ์ต่อไปนี้

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

.round()หรือ.setScale()? ฉันจะไปเกี่ยวกับเรื่องนี้ได้อย่างไร?

คำตอบ:


156

คุณสามารถใช้setScale()เพื่อลดจำนวนหลักเศษส่วนให้เป็นศูนย์ สมมติว่าvalueเก็บค่าที่จะปัดเศษ:

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

การใช้round()มีความเกี่ยวข้องมากกว่าเล็กน้อยเนื่องจากคุณต้องระบุจำนวนหลักที่จะเก็บไว้ ในตัวอย่างของคุณนี่จะเป็น 3 แต่ไม่สามารถใช้ได้กับทุกค่า:

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

(โปรดทราบว่าBigDecimalวัตถุไม่เปลี่ยนรูปทั้งสองอย่างsetScaleและroundจะส่งคืนวัตถุใหม่)


1
ไม่ทำงาน: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75
Boris Pavlović

3
ไม่การตั้งค่ามาตราส่วนจะส่งคืนทศนิยมใหม่ที่ไม่เหมือนกับครั้งแรก ตัวอย่างเช่นBigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));พิมพ์เท็จ
Daniel Fath

6
@ แดเนียล: นั่นมีนัยอยู่แล้วในข้อมูลโค้ดที่ฉันโพสต์ไว้ในคำตอบของฉัน ตอนนี้ฉันได้ทำให้มันชัดเจนแล้ว
Grodriguez

RoundingModeนั่นคืออะไร? มันBigDecimal
ตอนจบ


10

ถ้าฉันทำตามคำตอบของ Grodriguez

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

นี่คือผลลัพธ์

100.23 -> 100
100.77 -> 101

ซึ่งมันไม่ตรงกับที่ฉันต้องการฉันเลยลงเอยด้วยการทำแบบนี้ ..

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

นี่คือสิ่งที่ฉันได้รับ

100.23 -> 100.00
100.77 -> 101.00

นี่ช่วยแก้ปัญหาของฉันได้ในตอนนี้ .. :) ขอบคุณทุกคน


7
ฉันอยากรู้เกี่ยวกับข้อความที่ว่าผลลัพธ์แรก "ไม่ตรงกับที่ฉันต้องการ ... " หากคุณกังวลเกี่ยวกับการจัดรูปแบบเอาต์พุตคุณสามารถใช้DecimalFormat(เช่นเดียวกับในnew DecimalFormat("###.00")) เพื่อจัดการการแปลงBigDecimalกลับเป็นสตริง มันให้"101.00"ผลลัพธ์สำหรับทั้งสองค่าที่ตัวอย่างจาก @Grodriquez และคุณสร้างขึ้น
joel.neely

3
ครั้งที่สองที่คุณปัดเศษที่นี่ไม่จำเป็นเนื่องจากคุณรู้ว่าคุณมีจำนวนเต็มอยู่แล้วดังนั้นฉันจะใช้ BigDecimal.ROUND_UNNECESSARY แทนซึ่งชัดเจนกว่าเล็กน้อยในความคิดของฉัน
kosmoplan

5

นี่เป็นวิธีแก้ปัญหาที่ซับซ้อนมาก แต่ใช้งานได้:

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

รหัสทดสอบ:

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

เอาท์พุต:

100
100
101
101


ไม่ให้การรับรองโซลูชันนี้หรือสิ่งใด ๆ แต่input.toBigInteger().toString().length()ส่วนนี้จะมีประสิทธิภาพมากขึ้นโดยใช้ลอการิทึมเช่นround_up(log(input)) + (1 if input is a power of ten, else 0)
Addison

3

เพียงแค่ดูที่:

http://download.oracle.com/javase/6/docs/api/java/math/BigDecimal.html#ROUND_HALF_UP

และ:

setScale(int precision, int roundingMode)

หรือถ้าใช้ Java 6 ก็

http://download.oracle.com/javase/6/docs/api/java/math/RoundingMode.html#HALF_UP

http://download.oracle.com/javase/6/docs/api/java/math/MathContext.html

และอย่างใดอย่างหนึ่ง:

setScale(int precision, RoundingMode mode);
round(MathContext mc);

0

ฉันไม่คิดว่าคุณจะปัดเศษแบบนั้นได้ในคำสั่งเดียว ลอง

    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

ฉันทดสอบกับตัวอย่างที่เหลือของคุณและส่งคืนค่าที่ต้องการ แต่ไม่รับประกันความถูกต้อง


-2

คุณต้องการ

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

2
สิ่งนี้ไม่ได้ทำอะไรเลย จากเอกสารround: "ถ้าการตั้งค่าความแม่นยำเป็น 0 จะไม่มีการปัดเศษเกิดขึ้น"
Grodriguez
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.