Java BigDecimal: Làm tròn đến giá trị nguyên gần nhất


88

Tôi cần kết quả sau

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

.round()hoặc .setScale()? Làm thế nào để tôi đi về điều này?

Câu trả lời:


150

Bạn có thể sử dụng setScale()để giảm số lượng chữ số phân số xuống 0. Giả sử valuegiữ giá trị được làm tròn:

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

Việc sử dụng round()có liên quan nhiều hơn một chút vì nó yêu cầu bạn chỉ định số chữ số được giữ lại. Trong các ví dụ của bạn, giá trị này sẽ là 3, nhưng điều này không hợp lệ cho tất cả các giá trị:

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

(Lưu ý rằng BigDecimalcác đối tượng là bất biến; cả hai setScaleroundsẽ trả về một đối tượng mới.)


1
Nó không hoạt động: 100,12: 100,12, 100,44: 100,44, 100,50: 100,5, 100,75: 100,75
Boris Pavlović

3
Không, tỷ lệ cài đặt trả về một số thập phân mới không giống với số đầu tiên. Ví dụ: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));in sai
Daniel Fath

6
@Daniel: Điều đó đã được ngụ ý trong đoạn mã tôi đã đăng trong câu trả lời của mình. Bây giờ tôi đã làm cho nó rõ ràng.
Grodriguez vào

RoundingModeđó là gì? Đó làBigDecimal
bộ ba


10

Nếu tôi đi theo câu trả lời của Grodriguez

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

Đây là đầu ra

100.23 -> 100
100.77 -> 101

Đó không phải là những gì tôi muốn, vì vậy tôi đã kết thúc việc này ..

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

Đây là những gì tôi nhận được

100.23 -> 100.00
100.77 -> 101.00

Điều này giải quyết vấn đề của tôi bây giờ ..:) Cảm ơn tất cả các bạn.


7
Tôi tò mò về tuyên bố rằng kết quả đầu tiên "không hoàn toàn như những gì tôi muốn ...". Nếu bạn thực sự lo lắng về định dạng đầu ra, bạn có thể sử dụng DecimalFormat(như trong new DecimalFormat("###.00")) để quản lý việc chuyển đổi từ BigDecimaltrở lại thành chuỗi. Nó cung cấp "101.00"kết quả cho cả hai giá trị mà đoạn mã từ @Grodriquez và bạn đã tạo.
joel.neely

3
Lần thứ hai bạn làm tròn ở đây là không cần thiết vì bạn biết bạn đã có một số nguyên, vì vậy tôi sẽ sử dụng BigDecimal.ROUND_UNNECESSARY để thay thế, theo ý kiến ​​của tôi rõ ràng hơn một chút.
kosmoplan

5

Đây là một giải pháp cực kỳ phức tạp, nhưng nó hoạt động:

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

Mã kiểm tra:

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

Đầu ra:

100
100
101
101


Không ủng hộ giải pháp này hoặc bất cứ điều gì, nhưng input.toBigInteger().toString().length()một phần sẽ hiệu quả hơn bằng cách sử dụng một logarit, một số điều nhưround_up(log(input)) + (1 if input is a power of ten, else 0)
Addison


0

Tôi không nghĩ rằng bạn có thể làm tròn nó như vậy chỉ trong một lệnh. Thử

    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

Tôi đã kiểm tra các ví dụ còn lại của bạn và nó trả về các giá trị mong muốn, nhưng tôi không đảm bảo tính đúng đắn của nó.


-2

Bạn muốn

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

2
Điều này không làm gì cả. Từ tài liệu về round: "Nếu cài đặt độ chính xác là 0 thì không có làm tròn nào diễn ra."
Grodriguez vào
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.