new BigDecimal(0.7)
не не представляет 0,7.
Это 0,6999999999999999555910790149937383830547332763671875 (точно).
Причина этого в том, что double
литерал 0.7
не представляет 0,7 точно.
Если вам нужны точные BigDecimal
значения, вы должны использовать конструктор String
(на самом деле все конструкторы, которые не принимают double
значения будут работать).
Попробуйте new BigDecimal("0.7")
.
JavaDoc конструктора BigDecimal(double)
имеет несколько связанных замечаний:
Результаты этого конструктора могут быть несколько непредсказуемыми. Можно предположить, что запись new BigDecimal(0.1)
в Java создает BigDecimal
, который в точности равен 0,1 (немасштабированное значение 1 со шкалой 1), но фактически равен 0,1000000000000000055511151231257827021181583404541015625. Это потому, что 0,1 не может быть представлен точно как double
(или, в этом отношении, как двоичная дробь любой конечной длины). Таким образом, значение, которое передается в конструктор, не совсем равно 0,1, несмотря на внешний вид.
Конструктор String
, с другой стороны, совершенно предсказуем: запись new BigDecimal("0.1")
создает BigDecimal
, что на точно равно 0,1, как и следовало ожидать. Поэтому обычно рекомендуется использовать конструктор String
вместо этого.
Когда double
должен использоваться в качестве источника для BigDecimal
, обратите внимание, что этот конструктор обеспечивает точное преобразование; он не дает того же результата, что и преобразование double
в String
с использованием метода Double.toString(double)
, а затем с использованием конструктора BigDecimal(String)
. Чтобы получить такой результат, используйте метод static
valueOf(double)
.
Итак, подведем итог: если вы хотите создать BigDecimal
с фиксированным десятичным значением, используйте конструктор String
. Если у вас уже есть значение a double
, то BigDecimal.valueOf(double)
обеспечит более интуитивное поведение, чем использование new BigDecimal(double)
.