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

1044

То, что я хотел бы, это метод преобразования double в строку, которая округляется с использованием метода полураспада - т.е. если десятичное число округляется до 5, оно всегда округляется до предыдущего числа. Это стандартный метод округления большинства людей в большинстве ситуаций.

Мне также нужны только значимые цифры для отображения - т.е. не должно быть никаких конечных нулей.

Я знаю, что один из способов сделать это - использовать метод String.format:

String.format("%.5g%n", 0.912385);

возвращает:

0.91239

что отлично, однако он всегда отображает числа с 5 десятичными знаками, даже если они не значительны:

String.format("%.5g%n", 0.912300);

возвращает:

0.91230

Другим методом является использование DecimalFormatter:

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

возвращает:

0.91238

Однако, как вы видите, это использует округлое округление. То есть он округляется, если предыдущая цифра четная. Я бы хотел:

0.912385 -> 0.91239
0.912300 -> 0.9123

Каков наилучший способ достичь этого в Java?

Теги:
decimal
rounding
digits

31 ответ

630
Лучший ответ

Используйте setRoundingMode, установите RoundingMode явно для обработки вашей проблемы с полу-четным циклом, а затем используйте шаблон формата для требуемого вывода.

Пример:

DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
    Double d = n.doubleValue();
    System.out.println(df.format(d));
}

дает результат:

12
123.1235
0.23
0.1
2341234.2125
  • 8
    Это, вероятно, лучшее решение, представленное на данный момент. Причина, по которой я не заметил эту возможность, когда впервые увидел класс DecimalFormat, заключается в том, что он был представлен только в Java 1.6. К сожалению, я ограничен использованием 1.5, но это будет полезно знать в будущем.
  • 0
    Не работает с десятичными форматами экспоненты, скажем, в формате («0.0E00»). В этом примере он будет округлять 0,0155 до 0,0E00 вместо 1,6E-02.
Показать ещё 6 комментариев
401

Предполагая, что value является double, вы можете сделать:

(double)Math.round(value * 100000d) / 100000d

Это для 5 цифр точности. Число нулей указывает количество десятичных знаков.

  • 1
    Math.round использует внутренний бросок на long, который вы затем отбрасываете на удвоение.
  • 1
    Я думаю, что это лучше, чем при использовании DecimalFormat. DecimalFormat будет размещать различные объекты неявно, а также строку при каждом вызове decimalFormat.Format (). Я хотел бы представить, что лучше привести к нескольким приматам, чем распределять объекты.
Показать ещё 19 комментариев
156
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

вы получите BigDecimal. Чтобы получить строку из нее, просто вызовите этот метод BigDecimal toString или метод toPlainString для Java 5+ для строки в формате обычного формата.

Пример программы:

package trials;
import java.math.BigDecimal;

public class Trials {

    public static void main(String[] args) {
        int yourScale = 10;
        System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
    }
  • 33
    Это мое предпочтительное решение. Еще короче: BigDecimal.valueOf (doubleVar) .setScale (yourScaleHere, BigDecimal.ROUND_HALF_UP); BigDecimal.valueOf (double val) фактически вызывает Double.toString () под капотом;)
  • 3
    Ницца. Не new BigDecimal(doubleVar) углы и используйте new BigDecimal(doubleVar) как вы можете столкнуться с проблемами с округлением плавающих точек
Показать ещё 2 комментария
100

Вы также можете использовать

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

чтобы убедиться, что у вас есть конечные 0.

  • 22
    Я считаю , что одна из целей этого вопроса в том , что «не должно быть никаких замыкающие нули».
  • 7
    На этот вопрос оператору не нужны нули, но это именно то, что я хотел. Если у вас есть список чисел с 3 десятичными разрядами, вы хотите, чтобы все они имели одинаковые цифры, даже если это 0.
Показать ещё 2 комментария
78

Как отмечали некоторые другие, правильным ответом является использование DecimalFormat или BigDecimal. Плавающая точка не имеет десятичных знаков, поэтому вы не можете округлить/усечь до определенного числа из них в первую очередь. Вы должны работать в десятичной системе, и это то, что делают эти два класса.

Я отправляю следующий код в качестве контр-примера для всех ответов в этом потоке и даже по всему StackOverflow (и в другом месте), которые рекомендуют умножение с последующим усечением, за которым следует разделение. На адвокатов этой методики должно объясняться, почему следующий код производит неправильный вывод в более чем 92% случаев.

public class RoundingCounterExample
{

    static float roundOff(float x, int position)
    {
        float a = x;
        double temp = Math.pow(10.0, position);
        a *= temp;
        a = Math.round(a);
        return (a / (float)temp);
    }

    public static void main(String[] args)
    {
        float a = roundOff(0.0009434f,3);
        System.out.println("a="+a+" (a % .001)="+(a % 0.001));
        int count = 0, errors = 0;
        for (double x = 0.0; x < 1; x += 0.0001)
        {
            count++;
            double d = x;
            int scale = 2;
            double factor = Math.pow(10, scale);
            d = Math.round(d * factor) / factor;
            if ((d % 0.01) != 0.0)
            {
                System.out.println(d + " " + (d % 0.01));
                errors++;
            }
        }
        System.out.println(count + " trials " + errors + " errors");
    }
}

Вывод этой программы:

10001 trials 9251 errors

EDIT: Чтобы рассмотреть некоторые комментарии ниже, я new MathContext(16) часть тестового цикла с помощью BigDecimal и new MathContext(16) для работы модуля следующим образом:

public static void main(String[] args)
{
    int count = 0, errors = 0;
    int scale = 2;
    double factor = Math.pow(10, scale);
    MathContext mc = new MathContext(16, RoundingMode.DOWN);
    for (double x = 0.0; x < 1; x += 0.0001)
    {
        count++;
        double d = x;
        d = Math.round(d * factor) / factor;
        BigDecimal bd = new BigDecimal(d, mc);
        bd = bd.remainder(new BigDecimal("0.01"), mc);
        if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
        {
            System.out.println(d + " " + bd);
            errors++;
        }
    }
    System.out.println(count + " trials " + errors + " errors");
}

Результат:

10001 trials 4401 errors
  • 7
    Хитрость в том, что во всех ваших 9251 ошибках напечатанный результат все еще корректен.
  • 1
    @DidierL Это доказывает, что «напечатанный результат» и «результат» - это не одно и то же. На правильность «напечатанного результата» влияет то, что происходит во время печати. Только умножение и деление не решает проблему.
Показать ещё 17 комментариев
75

Предположим, что у вас есть

double d = 9232.129394d;

вы можете использовать BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

или без BigDecimal

d = Math.round(d*100)/100.0d;

с обоими решениями d == 9232.13

  • 2
    Я думаю, что это лучшее решение для пользователей Java 1.5 (и ниже). Один комментарий, не используйте режим округления HALF_EVEN, так как он имеет разностное поведение для нечетных и четных чисел (например, 2,5 округления до 2, а 5,5 округления до 6), если только это не то, что вы хотите.
  • 4
    Первое решение верное: второе не работает. Смотрите здесь для доказательства.
Показать ещё 7 комментариев
54

Вы можете использовать класс DecimalFormat.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));
  • 0
    Любая причина, почему Double.valueOf() был выбран Double.parseDouble() ? Метод valueOf() возвращает объект Double , а parseDouble() возвращает double примитив. При способе написания текущего кода вы также применяете автоматическую распаковку к возврату, чтобы привести его к примитиву, который ожидает ваша переменная twoDouble , - дополнительная операция с байт-кодом. Я бы изменил ответ, чтобы использовать вместо него parseDouble() .
  • 0
    Double.parseDouble() нуждается String ввода.
Показать ещё 1 комментарий
34

Real Java How-to публикует это решение, которое также совместимо для версий до версии Java 1.6.

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
30
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
  • 2
    да, это именно то, что math.round делает для положительных чисел, но вы пробовали это с отрицательными числами? люди используют math.round в других решениях, чтобы также покрыть случай отрицательных чисел.
  • 0
    Примечание: Math.floor(x + 0.5) и Math.round(x)
26

@Milhous: десятичный формат округления отлично:

Вы также можете использовать

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

чтобы убедиться, что у вас есть конечные 0.

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

Гипотетика: вам нужно внедрить механизм округления в графический интерфейс программа. Чтобы изменить точность/точность результата, просто измените формат каретки (т.е. в скобках). Так что:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

будет возвращаться как результат: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

будет возвращаться как результат: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

будет возвращаться как результат: 0.9124

[EDIT: также, если формат каретки подобен этому ( "# 0. ############" ), и вы введите десятичное число, например. 3.1415926, для аргументации, DecimalFormat не выводит мусор (например, завершающие нули) и возвращает: 3.1415926.. если вы так склонны. Конечно, это немного подробный для симпатии к некоторым dev - но hey, он получил низкую площадь памяти во время обработки и очень легко реализовать.]

Таким образом, красота DecimalFormat заключается в том, что она одновременно обрабатывает строку внешний вид - а также уровень точности округления. Эрго: ты получить два преимущества по цене одной реализации кода.;)

  • 2
    Если вам действительно нужны десятичные числа для расчета (и не только для вывода), не используйте двоичный формат с плавающей запятой, такой как double . Используйте BigDecimal или любой другой десятичный формат.
17

Вы можете использовать следующий метод утилиты -

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}
  • 2
    Не работает, смотрите здесь для доказательства.
  • 0
    Почему вы говорите, что это не работает? Это сработало для меня.
Показать ещё 4 комментария
15

Вот краткое описание того, что вы можете использовать, если хотите, чтобы результат был как String:

  • DecimalFormat # setRoundingMode():

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
    
  • BigDecimal # setScale()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
    

Вот пример того, какие библиотеки вы можете использовать, если хотите double в результате. Я бы не рекомендовал его для преобразования строк, хотя, поскольку double не может точно представлять то, что вы хотите (см., Например, здесь):

  • Precision от Apache Commons Math

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  • Functions от Colt

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  • Utils от Weka

    double rounded = Utils.roundDouble(0.912385, 5)
    
9

Кратким решением:

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

См. Также https://stackoverflow.com/questions/22186778/using-math-round-to-round-to-one-decimal-place Благодаря jpdymond для этого.

8

Вы можете использовать BigDecimal

BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);

Обратитесь: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

7

Попробуйте следующее: org.apache.commons.math3.util.Precision.round(double x, int scale)

Смотрите: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

Домашняя страница библиотеки математики Apache Commons: http://commons.apache.org/proper/commons-math/index.html

Внутренняя реализация этого метода:

public static double round(double x, int scale) {
    return round(x, scale, BigDecimal.ROUND_HALF_UP);
}

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new BigDecimal
               (Double.toString(x))
               .setScale(scale, roundingMethod))
               .doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}
6

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

  • Форматирование. Легко форматировать двойную строку с определенным количеством десятичных знаков.
  • Разбор: проанализируйте форматированное значение в двойном
  • Локаль: форматирование и синтаксический анализ с использованием локали по умолчанию
  • Экспоненциальная нотация. Начните использовать экспоненциальную нотацию после определенного порогового значения.

Использование довольно просто:

(Для этого примера я использую пользовательский язык)

public static final int DECIMAL_PLACES = 2;

NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);

String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"

double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345

Вот класс:

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;

public class NumberFormatter {

    private static final String SYMBOL_INFINITE           = "\u221e";
    private static final char   SYMBOL_MINUS              = '-';
    private static final char   SYMBOL_ZERO               = '0';
    private static final int    DECIMAL_LEADING_GROUPS    = 10;
    private static final int    EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
    private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation

    private DecimalFormat decimalFormat;
    private DecimalFormat decimalFormatLong;
    private DecimalFormat exponentialFormat;

    private char groupSeparator;

    public NumberFormatter(int decimalPlaces) {
        configureDecimalPlaces(decimalPlaces);
    }

    public void configureDecimalPlaces(int decimalPlaces) {
        if (decimalPlaces <= 0) {
            throw new IllegalArgumentException("Invalid decimal places");
        }

        DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
        separators.setMinusSign(SYMBOL_MINUS);
        separators.setZeroDigit(SYMBOL_ZERO);

        groupSeparator = separators.getGroupingSeparator();

        StringBuilder decimal = new StringBuilder();
        StringBuilder exponential = new StringBuilder("0.");

        for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
            decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
        }

        for (int i = 0; i < decimalPlaces; i++) {
            decimal.append("#");
            exponential.append("0");
        }

        exponential.append("E0");

        decimalFormat = new DecimalFormat(decimal.toString(), separators);
        decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
        exponentialFormat = new DecimalFormat(exponential.toString(), separators);

        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
        exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
    }

    public String format(double value) {
        String result;
        if (Double.isNaN(value)) {
            result = "";
        } else if (Double.isInfinite(value)) {
            result = String.valueOf(SYMBOL_INFINITE);
        } else {
            double absValue = Math.abs(value);
            if (absValue >= 1) {
                if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
                    value = Math.floor(value);
                    result = exponentialFormat.format(value);
                } else {
                    result = decimalFormat.format(value);
                }
            } else if (absValue < 1 && absValue > 0) {
                if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
                    result = decimalFormat.format(value);
                    if (result.equalsIgnoreCase("0")) {
                        result = decimalFormatLong.format(value);
                    }
                } else {
                    result = exponentialFormat.format(value);
                }
            } else {
                result = "0";
            }
        }
        return result;
    }

    public String formatWithoutGroupSeparators(double value) {
        return removeGroupSeparators(format(value));
    }

    public double parse(String value, double defValue) {
        try {
            return decimalFormat.parse(value).doubleValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return defValue;
    }

    private String removeGroupSeparators(String number) {
        return number.replace(String.valueOf(groupSeparator), "");
    }

}
5

На всякий случай кому-то все еще нужна помощь. Это решение отлично работает для меня.

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();

}

возвращает a String с желаемым выходом.

5

Если вам действительно нужны десятичные числа для вычисления (и не только для вывода), не используйте бинарный формат с плавающей запятой, такой как double.

Use BigDecimal or any other decimal-based format.

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

Фактически, я недавно использовал parsed-to-Long для получения точных представлений (в отличие от результатов hex) в графическом интерфейсе для чисел, больших как ################# ############### символов (в качестве примера).

4

Если вы используете DecimalFormat для преобразования double в String, это очень просто:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

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

3

Я пришел сюда просто, чтобы получить простой ответ о том, как округлить число. Это дополнительный ответ, чтобы обеспечить это.

Как округлить число в Java

Наиболее распространенным случаем является использование Math.round().

Math.round(3.7) // 4

Числа округлены до ближайшего целого числа. Значение .5 округляется. Если вам нужно другое поведение округления, вы можете использовать одну из других функций Math. См. Сравнение ниже.

round

Как указано выше, это округляет до ближайшего целого числа. .5 округлые десятичные числа. Этот метод возвращает int.

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4

Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4

ceil

Любое десятичное значение округляется до следующего целого числа. Он переходит в ceil. Этот метод возвращает double.

Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0

Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0

floor

Любое десятичное значение округляется до следующего целого числа. Этот метод возвращает double.

Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0

Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0

rint

Это похоже на раунд в том, что десятичные значения округляются до ближайшего целого. Однако, в отличие от round, .5 значения округляются до четного целого. Этот метод возвращает double.

Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***

Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
  • 0
    Я получил отрицательный голос, но я не уверен, что не так, поэтому я не знаю, что изменить.
  • 0
    вы решаете только конкретный случай округления до 0 десятичных дробей. Оригинальный вопрос более общий.
Показать ещё 1 комментарий
3

Я согласен с выбранным ответом на использование DecimalFormat --- или альтернативно BigDecimal.

Сначала прочитайте Обновить!

Однако, если вы хотите округлить двойное значение и получить результат значения double, вы можете использовать org.apache.commons.math3.util.Precision.round(..), как указано выше. Реализация использует BigDecimal, медленна и создает мусор.

Аналогичный, но быстрый и не содержащий мусора метод предоставляется утилитой DoubleRounder в библиотеке decimal4j:

 double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

Выведет

 0.667
 0.666
 1000.0
 9.00800700601E10

См https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

Отказ от ответственности: я участвую в проекте decimal4j.

Update: Как отметил @iaforek, DoubleRounder иногда возвращает неточностные результаты. Причина в том, что он выполняет математически правильное округление. Например, DoubleRounder.round(256.025d, 2) будет округлено до 256.02, потому что двойное значение, представленное как 256.025d, несколько меньше, чем рациональное значение 256.025 и, следовательно, будет округлено.

Примечания:

  • Такое поведение очень похоже на конструктор BigDecimal(double) (но не на valueOf(double), который использует конструктор строк).
  • Сначала проблему можно обойти с двойным округлением до более высокой точности, но это сложно, и я не буду вдаваться в подробности здесь.

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

  • 0
    Есть ли у вас показатели, показывающие, насколько эффективно ваше решение по сравнению с другими?
  • 0
    Я не сравнивал его с другими решениями, но в исходном коде доступен бенчмарк jmh: github.com/tools4j/decimal4j/blob/master/src/jmh/java/org/… Я запускал бенчмарк на ВМ результаты доступны в виде CSV-файла здесь: github.com/tools4j/decimal4j/wiki/Performance
Показать ещё 2 комментария
3

Ниже приведен фрагмент кода, показывающий, как отображать n цифр. Фокус в том, чтобы установить переменную pp в 1, за которой следуют n нулей. В приведенном ниже примере переменное значение pp имеет 5 нулей, поэтому будут отображаться 5 цифр.

double pp = 10000;

double myVal = 22.268699999999967;
String needVal = "22.2687";

double i = (5.0/pp);

String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
2

Для этого мы можем использовать этот форматтер:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

или:

DecimalFormat df = new DecimalFormat("0.00"); :

Используйте этот метод для получения двух десятичных знаков:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Определение этих значений:

91.32
5.22
11.5
1.2
2.6

Используя этот метод, мы можем получить следующие результаты:

91.32
5.22
11.50
1.20
2.60

демо онлайн.

2

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

Math.round(selfEvaluate*100000d.0)/100000d.0;

ИЛИ

Math.round(selfEvaluate*100000d.0)*0.00000d1;

Если вам нужно большое значение десятичных знаков, вы можете использовать BigDecimal. В любом случае .0 важно. Без него округление 0,333333d5 возвращает 0,33333 и допускается только 9 цифр. Вторая функция без .0 имеет проблемы с возвратом 0.30000 0.30000000000000004.

1

Имейте в виду, что String.format() и DecimalFormat производят строку, используя стандартную локаль. Таким образом, они могут писать форматированное число с точкой или запятой в качестве разделителя между целыми и десятичными частями. Чтобы убедиться, что округленная строка находится в формате, который вы хотите использовать java.text.NumberFormat, так:

  Locale locale = Locale.ENGLISH;
  NumberFormat nf = NumberFormat.getNumberInstance(locale);
  // for trailing zeros:
  nf.setMinimumFractionDigits(2);
  // round to 2 digits:
  nf.setMaximumFractionDigits(2);

  System.out.println(nf.format(.99));
  System.out.println(nf.format(123.567));
  System.out.println(nf.format(123.0));

Будет печататься на английском языке (независимо от вашего региона): 0,99 123,57 123.00

Пример из Farenda - как правильно преобразовать double в String.

0

Если вы используете технологию с минимальным JDK. Вот путь без каких-либо Java-библиотек:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
0
DecimalFormat myFormatter = new DecimalFormat("0.000");
String output = myFormatter.format(2.34d);
0

Если вы рассматриваете 5 или n число десятичных чисел. Может быть, этот ответ решает вашу проблему.

    double a = 123.00449;
    double roundOff1 = Math.round(a*10000)/10000.00;
    double roundOff2 = Math.round(roundOff1*1000)/1000.00;
    double roundOff = Math.round(roundOff2*100)/100.00;

    System.out.println("result:"+roundOff);

Вывод будет: 123.0 1
это можно решить с помощью петлевой и рекурсивной функции.

0

Где dp = десятичное место, которое вы хотите, и значение является двойным.

    double p = Math.pow(10d, dp);

    double result = Math.round(value * p)/p;
  • 1
    Производит 1.0 для value = 1.005 и dp = 2 . Используйте это вместо этого.
  • 0
    это нормально, Мэтт, твой пример недействителен. потому что 1.005 не может быть представлен в двойных числах с плавающей точкой в любом случае. он должен действительно храниться выше или ниже 1,005, т. е. при компиляции он хранится как двойное число: 1.0049998 (в скомпилированном коде оно не хранится как десятичное число, как вы могли бы поверить читателям) цель верна, он хранит значения как числа с плавающей запятой двойной, где крайние случаи, подобные твоему, в любом случае незначительны. если бы это было так, то вы бы использовали 3dp, затем конвертировали бы его в десятичную, а затем выполняли бы функцию десятичного раунда, точно так же, как и размещенную вами ссылку.
Показать ещё 1 комментарий
-1

В общем, округление выполняется путем масштабирования: round(num/p) * p

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the edge cases).
 */
double RoundCorrect(double num, int precision) {
    double c = 0.5 * EPSILON * num;
//  double p = Math.pow(10, precision); //slow
    double p = 1; while (precision--> 0) p *= 10;
    if (num < 0)
        p *= -1;
    return Math.round((num + c) * p) / p;
}

// testing edge cases
RoundCorrect(1.005, 2);   // 1.01 correct
RoundCorrect(2.175, 2);   // 2.18 correct
RoundCorrect(5.015, 2);   // 5.02 correct

RoundCorrect(-1.005, 2);  // -1.01 correct
RoundCorrect(-2.175, 2);  // -2.18 correct
RoundCorrect(-5.015, 2);  // -5.02 correct
-1

В принципе, метод round() возвращает ближайший long или int, как указано возвращаемым типом метода, аргументу:

public class Test{ 
    public static void main(String args[]){ 
    double d = 100.675;
    double e = 100.500;
    float f = 100;
    float g = 90f;
    System.out.println (Math.round(d));
    System.out.println (Math.round(e)); 
    System.out.println (Math.round(f)); 
    System.out.println (Math.round(g)); 
    }
}

И это дает результат:

101
101
100
90

Ещё вопросы

Сообщество Overcoder
Наверх
Меню