Ответ
Тип double (и float) реализует арифметику с плавающей запятой согласно стандарту IEEE 754, что приводит к погрешностям округления при работе с десятичными дробями. Это делает его непригодным для точных вычислений, таких как финансовые операции.
Проблема на примере:
double a = 0.1;
double b = 0.2;
double sum = a + b;
System.out.println(sum); // 0.30000000000000004
System.out.println(sum == 0.3); // false!
Десятичные дроби (как 0.1) часто не имеют точного двоичного представления, что вызывает накопление ошибок.
Решение:
-
BigDecimal(основной выбор)- Хранит число как строку и выполняет вычисления с заданной точностью (
MathContext).BigDecimal a = new BigDecimal("0.1"); // Важно: использовать строковый конструктор! BigDecimal b = new BigDecimal("0.2"); BigDecimal sum = a.add(b); System.out.println(sum.equals(new BigDecimal("0.3"))); // true
- Хранит число как строку и выполняет вычисления с заданной точностью (
-
Целочисленное хранение в минимальных единицах
- Хранить сумму в копейках, центах и т.д. в типе
longилиBigInteger.long priceInCents = 199; // 1.99 USD
- Хранить сумму в копейках, центах и т.д. в типе
Вывод: Для любых расчётов, где важна точность (деньги, проценты, научные измерения), всегда используйте BigDecimal.