Мы знаем, что использование double для валюты подвержено ошибкам и не рекомендуется. Тем не менее, я еще не видел пример  реалистичный, где BigDecimal работает, пока double терпит неудачу и не может быть просто исправлен некоторым округлением.
Заметим, что тривиальные задачи
double total = 0.0;
for (int i = 0; i < 10; i++) total += 0.1;
for (int i = 0; i < 10; i++) total -= 0.1;
assertTrue(total == 0.0);
не учитываются, поскольку они тривиально решаются путем округления (в этом примере все должно быть от нуля до шестнадцати знаков после запятой).
Вычисления с суммированием больших значений могут потребовать некоторого промежуточного рутинга, но при условии, что общая сумма валюты  равна USD 1e12, Java double ( т.е. стандартная двойная точность IEEE) с ее 15 десятичными цифрами по-прежнему является достаточным событием для центов.
Вычисления с делением вообще неточны даже при BigDecimal. Я могу построить вычисление, которое не может быть выполнено с помощью double s, но может быть выполнено с помощью BigDecimal с использованием шкалы 100, но это не то, с чем вы можете столкнуться в действительности.
Я не утверждаю, что такого реалистического примера не существует, просто я этого еще не видел.
Я также уверен, что использование double более подвержено ошибкам.
Пример
То, что я ищу, - это метод, подобный следующему (на основе ответа Роланда Иллига)
/** 
  * Given an input which has three decimal places,
  * round it to two decimal places using HALF_EVEN.
*/
BigDecimal roundToTwoPlaces(BigDecimal n) {
    // To make sure, that the input has three decimal places.
    checkArgument(n.scale() == 3);
    return n.round(new MathContext(2, RoundingMode.HALF_EVEN));
}
вместе с тестом вроде
public void testRoundToTwoPlaces() {
    final BigDecimal n = new BigDecimal("0.615");
    final BigDecimal expected = new BigDecimal("0.62");
    final BigDecimal actual = roundToTwoPlaces(n);
    Assert.assertEquals(expected, actual);
}
Когда это становится наивно переписанным с помощью double, тогда тест может потерпеть неудачу (он не для данного ввода, но для других). Однако это можно сделать правильно:
static double roundToTwoPlaces(double n) {
    final long m = Math.round(1000.0 * n);
    final double x = 0.1 * m;
    final long r = (long) Math.rint(x);
    return r / 100.0;
}
Он уродливый и подверженный ошибкам (и, вероятно, может быть упрощен), но его можно легко инкапсулировать где-то. Вот почему я ищу больше ответов.
