Java BigDecimal: округлення до найближчого цілого значення


90

Мені потрібні наступні результати

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

.round()чи .setScale()? Як я можу це зробити?

Відповіді:


153

Можна використовувати 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
Борис Павлович

3
Ні, установка шкали повертає новий десятковий знак, який не є таким, як перший. Наприклад: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));друкує помилково
Даніель Фат,

6
@Daniel: Це вже було передбачено у фрагменті коду, який я розмістив у своїй відповіді. Зараз я зробив це чітко.
Гродрігес

RoundingModeщо це? ЦеBigDecimal
трилогія


10

Якщо я піду на відповідь Гродрігеса

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")) для управління перетворенням BigDecimalback у рядок. Це дає "101.00"результат для обох значень, які створили фрагменти від @Grodriquez.
joel.neely

3
Другий раз, коли ви округляєте тут, зайвий, оскільки ви знаєте, що у вас уже є ціле число, тому я б використав замість цього BigDecimal.ROUND_UNNECESSARY, на мою думку, трохи чіткіше.
космоплан

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)
Аддісон

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, то округлення не відбувається".
Гродрігес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.