1. Обзор
В этом коротком руководстве мы узнаем, как округлить число до n
знаков после запятой в Java.
2. Десятичные числа в Java
Java предоставляет два примитивных типа, которые мы можем использовать для хранения десятичных чисел: float
и double
. Двойной
тип по умолчанию:
double PI = 3.1415;
Однако мы никогда не должны использовать любой тип для точных значений , таких как валюты. Для этого, а также для округления мы можем использовать класс BigDecimal .
3. Форматирование десятичного числа
Если мы просто хотим напечатать десятичное число с n
цифрами после запятой, мы можем просто отформатировать выходную строку:
System.out.printf("Value with 3 digits after decimal point %.3f %n", PI);
// OUTPUTS: Value with 3 digits after decimal point 3.142
В качестве альтернативы мы можем отформатировать значение с помощью класса DecimalFormat
:
DecimalFormat df = new DecimalFormat("###.###");
System.out.println(df.format(PI));
DecimalFormat
позволяет нам явно установить поведение округления, предоставляя больший контроль над выводом, чем String.format(),
использованный выше.
4. Округление двойных
чисел с помощью BigDecimal
Чтобы округлить double
s до n
знаков после запятой, мы можем написать вспомогательный метод :
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 :
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.5</version>
</dependency>
Последнюю версию можно найти здесь .
Как только мы добавим библиотеку в проект, мы можем использовать метод Precision.round()
, который принимает два аргумента — значение и масштаб:
Precision.round(PI, 3);
По умолчанию он использует тот же метод округления HALF_UP
, что и наш вспомогательный метод; следовательно, результаты должны быть одинаковыми.
Обратите внимание, что мы можем изменить поведение округления, передав желаемый метод округления в качестве третьего параметра.
5. Округление двойников с помощью DoubleRounder
DoubleRounder
— это утилита в библиотеке decimal4j . Он обеспечивает быстрый и безотходный метод округления двойных значений от 0 до 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 instead of expected 256.03
6. Метод Math.round()
Другой способ округления чисел — использовать метод Math.Round()
.
В этом случае мы можем контролировать n
количество знаков после запятой, умножив и разделив на 10^n
:
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));
// OUTPUTS: 92.23372036854776 !!
System.out.println(roundAvoid(260.775d, 2));
// OUTPUTS: 260.77 instead of expected 260.78
В результате этот метод указан здесь только в учебных целях.
7. Заключение
В этой статье мы рассмотрели различные способы округления чисел до n
знаков после запятой.
Мы можем просто отформатировать вывод без изменения значения или округлить переменную с помощью вспомогательного метода. Мы также обсудили несколько библиотек, решающих эту проблему.
Код, использованный в этой статье, можно найти на GitHub .