Mostrando entradas con la etiqueta decimal. Mostrar todas las entradas
Mostrando entradas con la etiqueta decimal. Mostrar todas las entradas

10 abr 2014

Problemas con el separador de los números decimales (punto o coma) en Java

En ocasiones podemos tener problemas con el formato de los números decimales, ya que el carácter que separa la parte entera, de la parte decimal, puede ser un punto o una coma. Depende del idioma que tenga configurado por defecto el sistema operativo. Si tenemos configurado español y escribimos un número con decimales, escribirá la coma, pero si leemos un número escrito de esta forma e intentamos asignárselo a un float nos dará error porque está esperando un punto, que es el formato interno con el que trabaja el compilador.
Por ejemplo el siguiente código:
public void leerVectorDiscos() throws FileNotFoundException     {
        Scanner sc = new Scanner(new File("archivo.txt"));
        String fila;
        String[] vectSt;
        for (int j=0;j<hd.length;j++)
        {
            fila=sc.nextLine();
            vectSt=fila.split("\t");
            hd[j].setTecnologia(vectSt[0]); 
            hd[j].setCapacidad(Integer.parseInt(vectSt[1]));
            hd[j].setVelocidad(Float.parseFloat(vectSt[2]));
        }
        sc.close();
}
producirá esta excepción:
Exception in thread "main" java.lang.NumberFormatException: For input string: "9600,00"
            at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
            at java.lang.Float.parseFloat(Float.java:452)
            at java500_1.VectorDiscos.leerVectorDiscos(VectorDiscos.java:118)
            at java500_1.Java500_1.main(Java500_1.java:36)
Java Result: 1

Una solución es utilizar la clase Numberformat, para especificar el formato que va a tener un número decimal:
float numf;
Locale spanish = new Locale(“es”, “ES”);
NumberFormat nf= NumberFormat.getInstance(spanish);
numf= nf.parse(st[2]).floatValue();

Hay que incluir los correspondientes import:
import java.text.NumberFormat;
import java.util.Locale;

De esta forma como estamos indicando que el idioma local es español, tomará la coma como separador decimal al hacer el parseo. El código resultante sería:
public void leerVectorDiscos() throws FileNotFoundException , ParseException     {
        Scanner sc = new Scanner(new File("archivo.txt"));
        String fila;
        String[] vectSt;
        for (int j=0;j<hd.length;j++)
        {
            fila=sc.nextLine();
            vectSt=fila.split("\t");
            hd[j].setTecnologia(vectSt[0]); 
            hd[j].setCapacidad(Integer.parseInt(vectSt[1]));
            Locale spanish = new Locale(“es”, “ES”);
            NumberFormat nf= NumberFormat.getInstance(spanish);
            hd[j].setVelocidad(nf.parse(vectSt[2]).floatValue());
        }
        sc.close();
}

Hay que tener cuidado porque crear una instancia de Locale, no sólo cambia el separador sino también el resto de características asociadas al idioma, como puede ser la moneda o los formatos de fecha y hora.
Una solución alternativa puede ser utilizar un objeto de la clase DecimalFormat, derivada de NumberFormat, que toma la configuración de los números del idioma del sistema operativo que tengamos instalado:
public void leerVectorDiscos() throws FileNotFoundException , ParseException     {
        Scanner sc = new Scanner(new File("archivo.txt"));
        String fila;
        String[] vectSt;
        for (int j=0;j<hd.length;j++)
        {
            fila=sc.nextLine();
            vectSt=fila.split("\t");
            hd[j].setTecnologia(vectSt[0]); 
            hd[j].setCapacidad(Integer.parseInt(vectSt[1]));
            DecimalFormat df= new DecimalFormat();
            hd[j].setVelocidad(df.parse(vectSt[2]).floatValue());
        }
        sc.close();
}

La clase DecimalFormat permite además especificar máscaras, con el formato de presentación que queramos, mediante el constructor, y unos caracteres especificados, con el carácter ‘#’, si el número no tiene una cifra no aparecería, y con el ‘0’, aparecería un ‘0’, por ejemplo:
DecimalFormat df = DecimalFormat(“###.##”);
System.out.println (df.format (2.3));                    //Sacaría 2,3
System.out.println (df.format (2.357));               //Sacaría 2,35
System.out.println (df.format (4322.3));             //Sacaría 4322,3

DecimalFormat df = DecimalFormat(“000.00”);
System.out.println (df.format (2.3));                    //Sacaría 002,30
System.out.println (df.format (2.357));                //Sacaría 002,35
System.out.println (df.format (4322.3));             //Sacaría 4322,3


Existen más caracteres que pueden utilizarse en la máscara, descritos en la API de DecimalFormat.