190 votos

¿Cómo imprimo un valor doble sin notación científica utilizando Java?

Quiero imprimir un valor double en Java sin la forma exponencial.

double dexp = 12345678;
System.out.println("dexp: "+dexp);

Muestra esta notación E: 1.2345678E7.

Quiero que se imprima así: 12345678

¿Cuál es la mejor manera de evitar esto?

216voto

Eric Leschinski Puntos 14289

Java prevenir la notación E en un double:

Cinco formas diferentes de convertir un double a un número normal:

import java.math.BigDecimal;
import java.text.DecimalFormat;

public class Runner {
    public static void main(String[] args) {
        double myvalue = 0.00000021d;

        //Opción 1 Imprimir el bare double.
        System.out.println(myvalue);

        //Opción 2, usar DecimalFormat.
        DecimalFormat df = new DecimalFormat("#");
        df.setMaximumFractionDigits(8);
        System.out.println(df.format(myvalue));

        //Opción 3, usar printf.
        System.out.printf("%.9f", myvalue);
        System.out.println();

        //Opción 4, convertir a BigDecimal y solicitar toPlainString().
        System.out.print(new BigDecimal(myvalue).toPlainString());
        System.out.println();

        //Opción 5, String.format 
        System.out.println(String.format("%.12f", myvalue));
    }
}

Este programa imprime:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000

Que son todos el mismo valor.

Protip: Si estás confundido acerca de por qué esos dígitos aleatorios aparecen más allá de cierto umbral en el valor double, este video lo explica: computerphile por qué 0.1+0.2 es igual a 0.30000000000001?

http://youtube.com/watch?v=PZRI1IfStY0

103voto

NPE Puntos 169956

Puedes usar printf() con %f:

double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);

Esto imprimirá dexp: 12345678.000000. Si no deseas la parte fraccionaria, utiliza

System.out.printf("dexp: %.0f\n", dexp);

El 0 en %.0f significa 0 lugares en la parte fraccionaria, es decir, sin parte fraccionaria. Si quieres imprimir la parte fraccionaria con un número deseado de decimales, en lugar de 0 simplemente proporciona el número como este %.8f. Por defecto, la parte fraccionaria se imprime hasta 6 decimales.

Esto utiliza el lenguaje de especificación de formato explicado en la documentación.

El formato predeterminado de toString() utilizado en tu código original se detalla aquí.

82voto

JBE Puntos 998

En resumen:

Si desea deshacerse de los ceros finales y los problemas de idioma, entonces debería usar:

double myValue = 0.00000021d;

DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS

System.out.println(df.format(myValue)); // Salida: 0.00000021

Explicación:

Por qué otras respuestas no me convencieron:

  • Double.toString() o System.out.println o FloatingDecimal.toJavaFormatString utiliza notaciones científicas si el double es menor de 10^-3 o mayor o igual a 10^7

  • Al usar %f, la precisión decimal predeterminada es 6, de lo contrario, puede codificarla directamente, pero genera ceros adicionales si tiene menos decimales. Ejemplo:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Salida: 0.000000210000
  • Al usar setMaximumFractionDigits(0); o %.0f elimina cualquier precisión decimal, lo cual está bien para enteros/longs, pero no para doubles:

    double myValue = 0.00000021d;
    System.out.println(String.format("%.0f", myvalue)); // Salida: 0
    DecimalFormat df = new DecimalFormat("0");
    System.out.println(df.format(myValue)); // Salida: 0
  • Al utilizar DecimalFormat, depende del idioma local. En la configuración regional francesa, el separador decimal es una coma, no un punto:

    double myValue = 0.00000021d;
    DecimalFormat df = new DecimalFormat("0");
    df.setMaximumFractionDigits(340);
    System.out.println(df.format(myvalue)); // Salida: 0,00000021

    Al usar la configuración regional ENGLISH se asegura de obtener un punto como separador decimal, dondequiera que se ejecute su programa.

¿Por qué usar 340 entonces para setMaximumFractionDigits?

Dos razones:

  • setMaximumFractionDigits acepta un entero, pero su implementación tiene un máximo de dígitos permitidos de DecimalFormat.DOUBLE_FRACTION_DIGITS que es igual a 340
  • Double.MIN_VALUE = 4.9E-324 así que con 340 dígitos se asegura de no redondear el double y perder precisión.

26voto

Obl Tobl Puntos 3091

Puedes probarlo con DecimalFormat. Con esta clase eres muy flexible al analizar tus números.
Puedes establecer exactamente el patrón que deseas utilizar.
En tu caso, por ejemplo:

double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678

8voto

NateS Puntos 1528

Esto funcionará siempre y cuando tu número sea un número entero:

double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);

Si la variable double tiene precisión después del punto decimal, se truncará.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X