Если вы запишите дробное значение, например 1 / 7
, в качестве десятичного значения, вы получите
1/7 = 0.142857142857142857142857142857142857142857...
с бесконечной последовательностью 142857
.Поскольку вы можете записать только конечное число цифр, вы неизбежно внесете ошибку округления (или усечения).
Числа, такие как 1/10
или 1/100
, выраженные в виде двоичных чисел с дробной частью, также имеют бесконечное числоцифр после десятичной точки:
1/10 = binary 0.0001100110011001100110011001100110...
Doubles
сохраняет значения в двоичном виде и, следовательно, может привести к ошибке исключительно путем преобразования десятичного числа в двоичное число, даже не выполняя никакой арифметики.
Десятичные числа (например, BigDecimal
), с другой стороны, хранят каждую десятичную цифру как есть.Это означает, что десятичный тип не является более точным, чем двоичный тип с плавающей запятой или тип с фиксированной запятой в общем смысле (например, он не может хранить 1/7
без потери точности), но он более точен для чисел с конечным числомдесятичные цифры, как это часто бывает при расчетах денег.
Java BigDecimal
имеет дополнительное преимущество, заключающееся в том, что он может иметь произвольное (но конечное) количество цифр с обеих сторон десятичной точки, ограниченное толькодоступная память.