Вопрос-ответ

Double vs. BigDecimal?

Double против BigDecimal?

Мне нужно вычислить некоторые переменные с плавающей запятой, и мой коллега предлагает мне использовать BigDecimal вместо double, так как это будет точнее. Но я хочу знать, что это такое и как извлечь максимальную пользу BigDecimal?

Переведено автоматически
Ответ 1

A BigDecimal - это точный способ представления чисел. A Double обладает определенной точностью. Работа с двойными числами различной величины (скажем, d1=1000.0 и d2=0.001) может привести к тому, что значение 0.001 при суммировании будет полностью отброшено, поскольку разница в величине очень велика. С BigDecimal этого бы не произошло.

Недостатком BigDecimal является то, что он медленнее, и таким образом немного сложнее программировать алгоритмы (из-за того, что он + - * и / не перегружен).

Если вы имеете дело с деньгами или точность обязательна, используйте BigDecimal. В остальном Doubles, как правило, достаточно хорош.

Я действительно рекомендую прочитать javadoc из BigDecimal, поскольку они объясняют вещи лучше, чем я здесь :)

Ответ 2

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

double a = 0.02;
double b = 0.03;
double c = b - a;
System.out.println(c);

BigDecimal _a = new BigDecimal("0.02");
BigDecimal _b = new BigDecimal("0.03");
BigDecimal _c = _b.subtract(_a);
System.out.println(_c);

Вывод программы:

0.009999999999999998
0.01

Кто-нибудь все еще хочет использовать double? ;)

Ответ 3

Есть два основных отличия от double:


  • Произвольная точность, аналогично BigInteger, они могут содержать число произвольной точности и размера (тогда как double имеет фиксированное количество битов)

  • Вместо основания 2 используется BigDecimal с основанием 10 n*10^-scale где n - произвольное целое число с большим знаком, а масштаб можно рассматривать как количество цифр для перемещения десятичной точки влево или вправо

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


  • Он может представлять все числа, которые могут быть представлены в десятичном виде, и это включает практически все числа в денежном мире (вы никогда не переводите 1/3 доллара кому-либо).

  • Точность можно контролировать, чтобы избежать накопления ошибок. С помощью a double по мере увеличения величины значения его точность уменьшается, и это может привести к существенной ошибке в результате.

Ответ 4

Если вы запишете дробное значение, например, 1 / 7 в виде десятичного значения, вы получите

1/7 = 0.142857142857142857142857142857142857142857...

с бесконечным повторением цифр 142857. Поскольку вы можете записать только конечное количество цифр, вы неизбежно приведете к ошибке округления (или усечения).

Числа типа 1/10 или 1/100, выраженные двоичными числами с дробной частью, также содержат бесконечное количество цифр после запятой:

1/10 = binary 0.0001100110011001100110011001100110...

Doubles хранит значения как двоичные и, следовательно, может привести к ошибке только при преобразовании десятичного числа в двоичное, даже без выполнения каких-либо арифметических действий.

Десятичные числа, с другой стороны, часто хранят каждую десятичную цифру как есть (в двоичном кодировании, но каждая десятичная цифра сама по себе) или, в случае BigDecimal, как два целых двоичных числа со знаком в форме x * 10y (спасибо @AlexSalauyou за указание). Смотрите: Класс BigDecimal. Это означает, что десятичный тип не более точен, чем двоичный тип с плавающей запятой или с фиксированной запятой в общем смысле (т. Е. Он не может хранить 1/7 без потери точности), но он более точен для чисел с конечным числом десятичных разрядов, как это часто бывает при денежных расчетах.

Java BigDecimal имеет дополнительное преимущество в том, что может содержать произвольное (но конечное) количество цифр по обе стороны от десятичной точки, ограниченное только доступной памятью.

2023-11-28 09:24 java