Pregunta

Tengo un valor doble = 1.068879335 Quiero redondearlo con solo dos valores decimales como 1.07.

Lo intenté así

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

Esto me está dando esta siguiente excepción

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

¿Alguien puede decirme qué está mal con mi código?

FINALY NECESITO EL FINALVALUE = 1.07;

¿Fue útil?

Solución

Tenga en cuenta la coma en su cadena: "1,07". DecimalFormat utiliza una cadena separadora específica de locales, mientras que Double.parseDouble() no es. Como vive en un país donde está el separador decimal ",", no puede revisar su número.

Sin embargo, puedes usar lo mismo DecimalFormat Para analizarlo:

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

Pero realmente deberías hacer esto en su lugar:

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

Nota: Como se ha señalado, solo debe usar el punto flotante si no necesita un control preciso sobre la precisión. (Los cálculos financieros son el principal ejemplo de cuándo no para usarlos.)

Otros consejos

Live @Sergey's Solution pero con Integer Division.

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

huellas dactilares

23.8764367843 rounded is 23.88

EDITAR: Como señala Sergey, no debe haber diferencia entre multiplar*int y doble*doble y dividir doble/int y doble/doble. No puedo encontrar un ejemplo donde el resultado sea diferente. Sin embargo, en x86/x64 y otros sistemas hay una instrucción específica del código de máquina para valores de doble mixto de doble, que creo que usa el 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);
}

Huellas dactilares

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

El problema es que utiliza un formato de localización que genera punto decimal específico de local, que es "," en su caso. Pero Double.ParsedOuble () espera doble literal no localizado. Puede resolver su problema utilizando un método de analización específico de locales o cambiando la ubicación de su formateador a algo que usa ". como el punto decimal. O incluso mejor, evite el formato innecesario usando algo como esto:

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

Hay algo fundamentalmente malo con lo que estás tratando de hacer. Los valores de puntos flotantes binarios no tener lugares decimales. No puede rodear de manera significativa a un número dado de lugares decimales, porque la mayoría de los valores decimales "redondos" simplemente no pueden representarse como una fracción binaria. Por eso uno nunca debe usar float o double representar dinero.

Entonces, si desea lugares decimales en su resultado, ese resultado debe ser un String (que ya tienes con el DecimalFormat), o un BigDecimal (que tiene un setScale() método que hace exactamente lo que quieres). De lo contrario, el resultado no puede ser lo que quiere que sea.

Leer La guía de punto flotante para más información.

Pruebe esto: org.apache.commons.math3.util.precision.round (doble x, int escala)

Ver:http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/precision.html

La página de inicio de la biblioteca de matemáticas de Apache Commons es:http://commons.apache.org/proper/commons-math/index.html

La implementación interna de este método es:

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;
        }
    }
}

Puede intentar definir un nuevo decimalformat y usarlo como resultado doble para una nueva variable doble.

Ejemplo dado para hacerte entender lo que acabo de decir.

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

Esto no es posible de la manera solicitada porque hay números con dos decimales que no se pueden expresar exactamente utilizando números de puntos flotantes IEEE (por ejemplo, 1/10 = 0.1 no se puede expresar como un Double o Float). El formato siempre debe ocurrir como el último paso antes de presentar el resultado al usuario.

Supongo que estás preguntando porque quieres lidiar con los valores monetarios. No hay forma de hacer esto de manera confiable con los números de punto flotante, debe considerar cambiar a aritméticos de punto fijo. Esto probablemente significa hacer todos los cálculos en "centavos" en lugar de "dólares".

double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

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

Puedes usar formato como aquí,

  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;   
    }
}

Si no desea usar decimalformat (por ejemplo, debido a su eficiencia) y desea una solución general, también puede probar este método que utiliza redondeo a escala:

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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top