Почему шкала BigDecimal не работает в Java?

Я несколько часов пытался получить правильные результаты с помощью BigDecimal.

У меня номер 7.7049. Я хочу сначала округлить до 3 цифр. Я возьму 7.705. Затем округлить до 2 цифр. У меня должно получиться 7,71.

Я пробовал это:

BigDecimal(result).setScale(2, RoundingMode.HALF_UP) //instead of 2 can be any other number

Но я получаю неправильный номер: 7.70.

Я пробовал разные режимы. Я тоже пробовал valueOf(result.toDouble()) и ничего не работает. Проблема здесь выглядит так: setScale работает только с двумя последними цифрами после . и игнорирует остальные.

Как я могу это исправить?

ОБНОВЛЕНО:

Еще примеры:

7,7019 должно быть 7,70 | 7,7052 должно быть 7,71 | 7,7071 должно быть 7,71 | 7,7030 должно быть 7,70

Как насчет RoundingMode.CEILING?

jrook 14.12.2020 17:56

@jrook Нет. Мне нужно простое математическое округление, а не всегда ВВЕРХ. Я имею в виду 7.7049 должно быть 7.71, но 7.7039 должно быть 7.70

Skullper 14.12.2020 17:59

Вы знаете, что делает RoundingMode.HALF_EVEN? Почему вы ожидаете, что 7,7049 станет 7,71? «Нормальное» округление сделает его равным 7,70, потому что ,049 ближе к ,0, чем к ,1.

luk2302 14.12.2020 18:00

Я не думаю, что существует модель округления, которая округляет 7,7049 до 7,71, но 7,7039 округляет до 7,71, потому что это не имеет смысла.

luk2302 14.12.2020 18:01

Пожалуйста, приведите больше примеров, чтобы прояснить, что вы действительно хотите сделать. 7.030 7.040 7.041 -7.039 и т. д. Кроме того, как отмечали другие комментаторы, это не обычное математическое округление, даже если оно каким-то образом достижимо. Вы можете обратиться к docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.htm‌​l

jrook 14.12.2020 18:12

Похоже, вы хотите сначала округлить 7.7049 до 7.705, а затем округлить до 7.71 - Округление 7.7049 округляет до 7.70

Dioxin 14.12.2020 18:22

@Dioxin Да, вот так, но одним действием, если это возможно

Skullper 14.12.2020 18:54

Нет ни одного действия, которое бы выполняло это округление так, как вы описали, потому что это такой необычный и нестандартный способ округления.

Louis Wasserman 14.12.2020 19:28

@LouisWasserman Большое спасибо за четкий комментарий

Skullper 14.12.2020 19:57
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
9
1 065
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете сначала округлить первые 3 цифры, а затем первые две цифры, чтобы получить то, что вы хотите.

BigDecimal a = new BigDecimal("7.7039")
    .setScale(3, RoundingMode.HALF_UP)
    .setScale(2, RoundingMode.HALF_UP);

Результаты совместимы с вашими тестовыми примерами. Я не проверял это для отрицательных чисел, и, вероятно, это не даст ожидаемых результатов для чисел с произвольной точностью.

Вы можете обратиться к документам RoundingMode и использовать эту идею, чтобы, возможно, придумать схему, которая округляет числа нестандартным способом, который вам нужен.

Проблема проста. У меня номер 7.7049. Когда я хочу округлить до 3 цифр после . Я получу 7,705, но когда я округлю это больше, чтобы 2 цифры я должен увидеть 7,71.

Вы уже упомянули, что вам нужно сделать, т.е. округлить сначала в масштабе 3, а затем в масштабе 2.

Демо:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
    public static void main(String[] args) {
        System.out.println(roundNumber(7.7019, 3, 2));
        System.out.println(roundNumber(7.7052, 3, 2));
        System.out.println(roundNumber(7.7071, 3, 2));
        System.out.println(roundNumber(7.7030, 3, 2));
        System.out.println(roundNumber(7.7049, 3, 2));
        System.out.println(roundNumber(7.7039, 3, 2));
    }

    static BigDecimal roundNumber(double num, int scaleRound1, int scaleRound2) {
        return new BigDecimal(num).setScale(scaleRound1, RoundingMode.HALF_UP).setScale(scaleRound2,
                RoundingMode.HALF_UP);
    }
}

Выход:

7.70
7.71
7.71
7.70
7.71
7.70

Другие вопросы по теме