Подтвердить что ты не робот

Двойное значение для округления в Java

У меня есть двойное value = 1.068879335 Я хочу округлить его только с двумя десятичными значениями, такими как 1.07.

Я пробовал вот так

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value);
double finalValue = Double.parseDouble(formate) ;

это дает мне следующее исключение

java.lang.NumberFormatException: For input string: "1,07"
     at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
     at java.lang.Double.parseDouble(Double.java:510)

может кто-нибудь сказать мне, что не так с моим кодом.

finaly Мне нужен finalValue = 1.07;

4b9b3361

Ответ 1

Обратите внимание на запятую в вашей строке: "1,07". DecimalFormat использует специфичную для локали строку разделителя, а Double.parseDouble() - нет. Поскольку вы живете в стране, где разделитель десятичных чисел ",", вы не можете проанализировать свой номер назад.

Однако вы можете использовать тот же DecimalFormat для его синтаксического анализа:

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value); 
double finalValue = (Double)df.parse(formate) ;

Но вы действительно должны это сделать:

double finalValue = Math.round( value * 100.0 ) / 100.0;

Примечание: Как уже указывалось, вы должны использовать только плавающие точки, если вам не нужен точный контроль точности. (Финансовые расчеты являются основным примером того, когда не использовать их.)

Ответ 2

Решение Live @Sergey, но с целым делением.

double value = 23.8764367843;
double rounded = (double) Math.round(value * 100) / 100;
System.out.println(value +" rounded is "+ rounded);

печатает

23.8764367843 rounded is 23.88

EDIT: Как указывает Сергей, не должно быть разницы между умножением double * int и double * double и делением double/int и double/double. Я не могу найти пример, когда результат отличается. Однако на x86/x64 и других системах существует определенная инструкция машинного кода для смешанных двойных значений int, которые, как я полагаю, использует JVM.

for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100) / 100;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,int operations %,d%n", time);
}
for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100.0) / 100.0;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,double operations %,d%n", time);
}

Печать

double,int operations 613,552,212
double,int operations 661,823,569
double,int operations 659,398,960
double,int operations 659,343,506
double,int operations 653,851,816
double,int operations 645,317,212
double,int operations 647,765,219
double,int operations 655,101,137
double,int operations 657,407,715
double,int operations 654,858,858
double,int operations 648,702,279
double,double operations 1,178,561,102
double,double operations 1,187,694,386
double,double operations 1,184,338,024
double,double operations 1,178,556,353
double,double operations 1,176,622,937
double,double operations 1,169,324,313
double,double operations 1,173,162,162
double,double operations 1,169,027,348
double,double operations 1,175,080,353
double,double operations 1,182,830,988
double,double operations 1,185,028,544

Ответ 3

Проблема заключается в том, что вы используете локализатор форматирования, который генерирует десятичную точку, специфичную для локали, которая является "," в вашем случае. Но Double.parseDouble() ожидает нелокализованный двойной литерал. Вы можете решить свою проблему, используя метод синтаксического анализа, специфичный для локали, или изменив языковой стандарт вашего форматирования на то, что использует ".". как десятичная точка. Или даже лучше избегайте ненужного форматирования, используя что-то вроде этого:

double rounded = (double) Math.round(value * 100.0) / 100.0;

Ответ 4

Есть что-то принципиально неправильное в том, что вы пытаетесь сделать. Значения двоичных значений с плавающей запятой не имеют десятичных знаков. Вы не можете осмысленно округлить до заданного количества десятичных знаков, потому что большинство "круглых" десятичных значений просто не могут быть представлены как двоичная дробь. Вот почему никогда не следует использовать float или double для представления денег.

Итак, если вы хотите десятичные места в вашем результате, этот результат должен быть либо String (который у вас уже есть с DecimalFormat), либо BigDecimal (который имеет метод setScale(), который точно выполняет что ты хочешь). В противном случае результат не может быть тем, чем вы хотите.

Подробнее читайте Руководство по плавающей запятой.

Ответ 5

Попробуйте следующее: 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

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

Пример, чтобы вы поняли, что я только что сказал.

double decimalnumber = 100.2397;
DecimalFormat dnf = new DecimalFormat( "#,###,###,##0.00" );
double roundednumber = new Double(dnf.format(decimalnumber)).doubleValue();

Ответ 7

Это невозможно в запрошенном порядке, потому что есть числа с двумя десятичными знаками, которые не могут быть точно выражены с использованием чисел с плавающей запятой IEEE (например, 1/10 = 0,1 не может быть выражено как Double или Float). Форматирование должно всегда выполняться как последний шаг перед представлением результата пользователю.

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

Ответ 8

double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

    TotalPrice = Double.valueOf(format_2Places.format(TotalPrice));

Ответ 9

Вы можете использовать формат здесь,

  public static double getDoubleValue(String value,int digit){
    if(value==null){
        value="0";
     }
    double i=0;
     try {
         DecimalFormat digitformat = new DecimalFormat("#.##");
         digitformat.setMaximumFractionDigits(digit);
        return Double.valueOf(digitformat.format(Double.parseDouble(value)));

    } catch (NumberFormatException numberFormatExp) {
        return i;   
    }
}

Ответ 10

Если вы не хотите использовать DecimalFormat (например, из-за его эффективности) и хотите общее решение, вы также можете попробовать этот метод, который использует масштабированное округление:

public static double roundToDigits(double value, int digitCount) {
    if (digitCount < 0)
        throw new IllegalArgumentException("Digit count must be positive for rounding!");

    double factor = Math.pow(10, digitCount);
    return (double)(Math.round(value * factor)) / factor;
}