Что выведет System.out.println(0.1 + 0.2 == 0.3) и что брать для денег?
false: 0.1 непредставимо точно в двоичной плавающей точке (IEEE 754), сумма даёт 0.30000000000000004. Для денег — BigDecimal из строки (new BigDecimal("0.1")) или копейки в long.
- double сравнивают с допуском: Math.abs(a − b) < eps
- new BigDecimal(0.1) уже содержит погрешность — BigDecimal.valueOf или строка
- BigDecimal.equals учитывает масштаб: 2.0 ≠ 2.00, сравнивать compareTo
А ещё Округление — явно: setScale(2, RoundingMode.HALF_EVEN)
Подробно
Дробные числа хранятся в двоичной плавающей точке, где 0.1 непредставимо точно, поэтому сумма даёт 0.30000000000000004. Сравнивать double на равенство нельзя — сравнивают с допуском (|a-b| < eps). Для денег берут BigDecimal и создают его из строки (new BigDecimal("0.1")), а не из double, иначе погрешность переедет внутрь.
Что хотят услышать
- Причина погрешности.
- BigDecimal и правильное создание.
- Сравнение double и BigDecimal.
Частые ошибки
- Хранить деньги в double/float.
- Создавать BigDecimal из double-литерала вместо строки.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗true — компилятор округлит; для денег подойдёт float
- ✓false — погрешность IEEE 754; для денег берут BigDecimal
- ✗true — double точен для таких чисел; деньги тоже храни в double
- ✗Ошибка компиляции: double нельзя сравнивать через ==
Что спросят дальше
- Почему new BigDecimal(0.1) хуже new BigDecimal("0.1")?
- Как корректно сравнить два double?
Разбор темы
- Примитивы, обёртки и Integer cache
Восемь примитивов и их диапазоны, autoboxing, кэш Integer и ловушка ==, NPE при распаковке и цена боксинга.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.