Когда тип BigDecimal сначала выполняет деление, а затем умножение, почему результат отличается от ожидаемого? ЯВА

Проблема: при использовании BigDecimal для нескольких вычислений с делением. трудно понять по десятичной дроби.

Например:

1/3*3

мы ожидаем 1

но когда вы используете BigDecimal.

мы получаем ArithmeticException

если я добавлю roundingMode для метода разделения.

получаем 0.9999999999999

float result1 = 1f / 3f * 3f;
BigDecimal one = BigDecimal.valueOf(1);
BigDecimal three = BigDecimal.valueOf(3);
BigDecimal result2 = one.divide(three,64,BigDecimal.ROUND_HALF_UP).multiply(three);

System.out.println(result1);
System.out.println(result2);

Выход

1.0
0.9999999999999999999999999999999999999999999999999999999999999999

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

Большое спасибо, если вы можете помочь предложить решение.

PS: Мой английский не очень хорош, я должен видеть, извините :)


person unreal    schedule 05.03.2021    source источник
comment
что вы хотите решить? вы хотите всегда получать 1? Почему? Проблема не в классе, а в цели операции. Вы пытаетесь представлять деньги или, например. физические расчеты? или другие типы операций (например, метки времени)? Решение зависит от использования, которое вам потребуется для результирующих операций.   -  person Victor Polo De Gyves Montero    schedule 05.03.2021
comment
Суть заключается в том, чтобы разделить сумму скидки заказа пропорционально продукту. Основной алгоритм: Общая скидка: N Сумма заказа: N Текущий продукт: MI Алгоритм округления (N/M · Mi) Мы хотим, чтобы результат N/M был как можно ближе к самому выражению И, конечно же, как программист, я также хочу понять, в чем заключается разница   -  person unreal    schedule 05.03.2021
comment
Это обширная тема, но, похоже, вы имеете дело с денежными операциями. Прямым предложением было бы: просто используйте long для представления центов для управления вашими денежными значениями. Это будет означать, что минимально возможное значение фиксировано и равно целому числу центов. Таким образом, стоимость 13250 центов (длинная) будет равна 132,50 долларам. Таким образом, вы избежите обсуждения BigDecimal и операций с плавающей запятой. Вам нужно будет помнить своему интерфейсу, что вы используете центы для представления единиц вашей национальной валюты, чтобы соответствующим образом исправить ваш интерфейс.   -  person Victor Polo De Gyves Montero    schedule 06.03.2021