Множество людей предложат использовать BigDecimal, и если вы не знаете, как использовать округления в вашем проекте, это то, что вам следует делать.
Если вы знаете, как правильно использовать десятичное округление, используйте double. Его на много порядков быстрее, намного понятнее и проще и, следовательно, меньше подвержено ошибкам ИМХО. Если вы используете доллары и центы (или вам нужны два десятичных знака), вы можете получить точный результат для значений до 70 триллионов долларов.
Как правило, вы не получите ошибок округления, если исправите их с помощью округления.
Кстати: мысль об округлении ошибок вселяет ужас в сердца многих разработчиков, но они не являются случайными ошибками, и вы можете управлять ими довольно легко.
РЕДАКТИРОВАТЬ: рассмотрим этот простой пример ошибки округления.
double a = 100000000.01;
double b = 100000000.09;
System.out.println(a+b); // prints 2.0000000010000002E8
Существует несколько возможных стратегий округления. Вы можете округлить результат при печати / просмотре. например,
System.out.printf("%.2f%n", a+b); // prints 200000000.10
или математически округлить результат
double c = a + b;
double r= (double)((long)(c * 100 + 0.5))/100;
System.out.println(r); // prints 2.000000001E8
В моем случае я округляю результат при отправке с сервера (запись в сокет и файл), но использую собственную процедуру, чтобы избежать создания какого-либо объекта.
Более общая функция округления выглядит следующим образом, но если вы можете использовать printf или DecimalFormat, может быть проще.
private static long TENS[] = new long[19]; static {
TENS[0] = 1;
for (int i = 1; i < TENS.length; i++) TENS[i] = 10 * TENS[i - 1];
}
public static double round(double v, int precision) {
assert precision >= 0 && precision < TENS.length;
double unscaled = v * TENS[precision];
assert unscaled > Long.MIN_VALUE && unscaled < Long.MAX_VALUE;
long unscaledLong = (long) (unscaled + (v < 0 ? -0.5 : 0.5));
return (double) unscaledLong / TENS[precision];
}
примечание: вы можете использовать BigDecimal для выполнения окончательного округления. особенно если вам нужен специальный метод раунда.