Как округлить число до N десятичных знаков в Java

Как округлить число до N десятичных знаков в Java

1. обзор

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

Дальнейшее чтение:

Количество цифр в целом числе в Java

Изучите различные способы получения количества цифр в Integer в Java.

Read more

Проверьте, простое ли число в Java

Узнайте, как проверить простоту числа с помощью Java.

Read more

Проверьте, является ли строка числовой в Java

Изучите различные способы определения, является ли строка числовой или нет.

Read more

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

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

double PI = 3.1415;

Однако оба типаshould never be used for precise values, например, валюты. Для этого, а также для округления мы можем использовать класс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. ОкруглениеDoubles наBigDecimal

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

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; мы должныalways use BigDecimal(String) constructor. Это предотвращает проблемы с представлением неточных значений.

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


    org.apache.commons
    commons-math3
    3.5

Последнюю версию можно найтиhere.

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

Precision.round(PI, 3);

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

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

5. Округление удвоений с помощьюDoubleRounder

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

Мы можем получить библиотеку (последнюю версию можно найтиhere), добавив зависимость кpom.xml:


    org.decimal4j
    decimal4j
    1.0.3

Теперь мы можем просто использовать:

DoubleRounder.round(PI, 3);

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

System.out.println(DoubleRounder.round(256.025d, 2));
// OUTPUTS: 256.02 instead of expected 256.03

6. Math.Round() Method

Другой способ округления чисел - использовать метод 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;
}

This method is not recommended as it’s truncating the value. Во многих случаях значения округляются неправильно:

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.

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

Код, использованный во время обсуждения, находится вover on GitHub.