Изучаем округление в Java: как в Java округлить число до n знаков после запятой

Округление в Java: обзор

В этой статье мы рассмотрим, как в Java округлить число до n десятичного знаков.

Десятичные числа в Java

Java предоставляет два примитивных типа, которые могут использоваться для хранения десятичных чисел: float и double. Double - это тип данных, используемый по умолчанию:

double PI = 3.1415

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

Форматирование десятичного числа

Если нужно вывести десятичное число с n знаками после запятой, можно отформатировать выходную строку:

System.out.printf("Value with 3 digits after decimal point %.3f %n", PI);	
// Вывод: Значения с 3 знаками после запятой 3.142

Также можно округлить значение с помощью класса DecimalFormat:

DecimalFormat df = new DecimalFormat("###.###");
System.out.println(df.format(PI));

Этот класс позволяет настроить процесс округления числа.

Java: округление Double с помощью BigDecimal

Чтобы округлить тип double до n знаков после запятой, можно написать helper-метод:

private static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();
 
    BigDecimal bd = new BigDecimal(Double.toString(value));
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

Обратите внимание, что при создании экземпляра класса BigDecimal мы должны всегда использовать конструктор BigDecimal(String). Это позволяет избежать проблем с представлением неточных значений.

Можно сделать то же самое, используя библиотеку Apache Commons Math:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
    <version>3.5</version>
</dependency>

Актуальную версию этой библиотеки можно найти здесь. Для округления чисел применяется метод Precision.round() , который принимает два аргумента - значение и масштаб:

Precision.round(PI, 3);

По умолчанию он использует тот же метод округления HALF_UP, что хэлпер. Поэтому результаты должны быть одинаковыми.

Кроме этого можно изменить процесс приведения чисел, передав в качестве третьего параметра необходимый метод округления.

Округление чисел с плавающей запятой с помощью DoubleRounder

DoubleRounder - это утилита из библиотеки decimal4j. Она предоставляет быстрый метод округления double чисел до 18 знаков после запятой.

Последнюю версию библиотеки можно найти здесь. Чтобы подключить ее, добавьте зависимость в файл pom.xml:

<dependency>
    <groupId>org.decimal4j</groupId>
    <artifactId>decimal4j</artifactId>
    <version>1.0.3</version>
</dependency>

Пример использования утилиты:

DoubleRounder.round(PI, 3);

Но DoubleRounder дает сбой в нескольких сценариях. Например:

System.out.println(DoubleRounder.round(256.025d, 2));
// OUTPUTS: 256.02 вместо ожидаемого 256.03

Метод Math.round() java

При использовании метода Math.round() можно контролировать п-количество десятичных разрядов путем умножения и деления на 10^п :

public static double roundAvoid(double value, int places) {
    double scale = Math.pow(10, places);
    return Math.round(value * scale) / scale;
}

Этот метод не рекомендуется использовать для округления чисел, поскольку он усекает значение. Во многих случаях значения округляются неправильно:

System.out.println(roundAvoid(1000.0d, 17));
// Вывод: 92.23372036854776 !!
System.out.println(roundAvoid(260.775d, 2));
// Вывод: 260.77 вместо ожидаемого 260.78

Заключение

В этой статье мы рассмотрели различные методы округления чисел до n знаков после запятой, доступные в Java.

Можно просто отформатировать вывод без изменения значения или округлить переменную с помощью вспомогательного метода или подключаемых библиотек.

Код, использованный в этой статье, доступен на GitHub.