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

Мне нужны следующие результаты

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

.round() или .setScale()? Как мне это сделать?


person n a    schedule 09.11.2010    source источник


Ответы (6)


Вы можете использовать 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 вернут новый объект.)

person Grodriguez    schedule 09.11.2010
comment
Не работает: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75 - person Boris Pavlović; 09.11.2010
comment
Нет, установка масштаба возвращает новое десятичное число, отличное от первого. Например: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2)); печатает false - person Daniel Fath; 09.11.2010
comment
@Daniel: Это уже подразумевалось во фрагменте кода, который я опубликовал в своем ответе. Я сейчас это ясно обозначил. - person Grodriguez; 09.11.2010
comment
RoundingMode что это? Это BigDecimal - person trilogy; 09.11.2018

Если я пойду по ответу Гродригеса

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

На данный момент это решает мою проблему ..:) Всем спасибо.

person n a    schedule 09.11.2010
comment
Мне любопытно утверждение, что первый результат - не совсем то, что я хочу ... Если вас действительно беспокоит форматирование вывода, вы можете использовать DecimalFormat (как в new DecimalFormat("###.00")) для управления преобразованием BigDecimal обратно в строку. Он дает "101.00" в качестве результата для обоих значений, созданных вами и фрагментами из @Grodriquez. - person joel.neely; 19.04.2016
comment
Во втором округлении здесь нет необходимости, поскольку вы знаете, что у вас уже есть целое число, поэтому я бы вместо этого использовал BigDecimal.ROUND_UNNECESSARY, что, на мой взгляд, немного более понятно. - person kosmoplan; 05.04.2017

Вот ужасно сложное решение, но оно работает:

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

person Sean Patrick Floyd    schedule 09.11.2010
comment
Не одобрять это решение или что-то в этом роде, но часть input.toBigInteger().toString().length() была бы намного эффективнее, если бы использовать логарифм, что-то вроде round_up(log(input)) + (1 if input is a power of ten, else 0) - person Addison; 21.05.2019

Просто посмотрите на:

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);
person toolkit    schedule 09.11.2010

Я не думаю, что это можно обойти с помощью одной команды. Пытаться

    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

Я протестировал остальные ваши примеры, и он возвращает требуемые значения, но я не гарантирую его правильность.

person Daniel Fath    schedule 09.11.2010

Вы хотите

round(new MathContext(0));  // or perhaps another math context with rounding mode HALF_UP
person jacobm    schedule 09.11.2010
comment
Это ничего не делает. Из документации round: Если параметр точности равен 0, округление не выполняется. - person Grodriguez; 09.11.2010