Java: ¿Cómo establecer la precisión para el doble valor?

Hace poco estaba trabajando con números y tuve una situación en la que deseo establecer la precisión de un valor doble, por ejemplo, en 6 dígitos o 4 dígitos, según el valor almacenado en la base de datos.

Por ejemplo, si en la base de datos la precisión se establece en 4 dígitos, entonces la salida debe verse como,

10.0000 .

Intenté con DecimalFormat y usando la cadena ##.#### , pero es molesto usar símbolos cada vez.

¿Hay algún mejor enfoque, di algo como a continuación?

 Double value = 10.0; value.setPrecision(4); 

No puede establecer la precisión de un doble (o doble) en un número especificado de dígitos decimales, porque los valores de coma flotante no tienen dígitos decimales. Ellos tienen dígitos binarios.

Tendrá que convertir en una base decimal, ya sea a través de BigDecimal o DecimalFormat , dependiendo de lo que quiera hacer con el valor más adelante.

Ver también mi respuesta a esta pregunta para refutar las inevitables * 100/100 respuestas.

Puedes probar BigDecimal para este propósito

 Double toBeTruncated = new Double("3.5789055"); Double truncatedDouble = BigDecimal.valueOf(toBeTruncated) .setScale(3, RoundingMode.HALF_UP) .doubleValue(); 

esta es una manera fácil de hacerlo.

 String formato = String.format("%.2f"); 

establece la presición en 2 dígitos o cualquiera.

si solo quieres imprimirlo, utiliza de esta manera.

 System.out.printf("%.2f",123.234); 

Para establecer la precisión de los valores dobles, DecimalFormat es una buena técnica. Para usar esta clase, importe java.text.DecimalFormat y cree un objeto para ello, por ejemplo

 double no=12.786; DecimalFormat dec = new DecimalFormat("#0.00"); System.out.println(dec.format(no)); 

Entonces imprimirá dos dígitos después del punto decimal aquí imprimirá 12.79

Esto funcionó para mí:

 public static void main(String[] s) { Double d = Math.PI; d = Double.parseDouble(String.format("%.3f", d)); // can be required precision System.out.println(d); } 

La precisión de double y float se determina por su tamaño y la forma en que se implementan los tipos de coma flotante IEEE .

El número de dígitos decimales en la salida, por otro lado, es una cuestión de formato. Tienes razón en que teclear la misma constante una y otra vez es una mala idea. En su lugar, debe declarar una cadena constante y usar su representación simbólica.

 private static final String DBL_FMT = "##.####"; 

Usar una representación simbólica le permitirá cambiar la precisión en todos los lugares donde se usa la constante sin buscar a través de su código.

Aquí hay una forma eficiente de lograr el resultado con dos advertencias.

  1. Limita la precisión a los dígitos N ‘máximos’ (no fijados a N dígitos).
  2. Redondea el número (no redondea al más cercano).

Vea ejemplos de casos de prueba aquí.

 123.12345678 ==> 123.123 1.230000 ==> 1.23 1.1 ==> 1.1 1 ==> 1.0 0.000 ==> 0.0 0.00 ==> 0.0 0.4 ==> 0.4 0 ==> 0.0 1.4999 ==> 1.499 1.4995 ==> 1.499 1.4994 ==> 1.499 

Aquí está el código. Las dos advertencias que mencioné anteriormente se pueden abordar con bastante facilidad, sin embargo, la velocidad me importaba más que la precisión, así que lo dejé aquí. Manipulaciones de cadena como System.out.printf("%.2f",123.234); son computacionalmente costosas en comparación con las operaciones matemáticas. En mis pruebas, el siguiente código (sin el sysout) tomó 1/30 del tiempo en comparación con las manipulaciones de cadenas.

 public double limitPrecision(String dblAsString, int maxDigitsAfterDecimal) { int multiplier = (int) Math.pow(10, maxDigitsAfterDecimal); double truncated = (double) ((long) ((Double.parseDouble(dblAsString)) * multiplier)) / multiplier; System.out.println(dblAsString + " ==> " + truncated); return truncated; } 
 BigDecimal value = new BigDecimal(10.0000); value.setScale(4); 

Para expandir en @EJP, el concepto de “precisión” cuando se trata de dobles es extremadamente tenso. Como se discutió en https://stackoverflow.com/a/3730040/390153 , ni siquiera puede representar 0.1 como un doble independientemente de la precisión, por la misma razón que no puede representar 1/3 en la base 10 con precisión finita.

Debe considerar el problema que está tratando de resolver y considerar:

a) ¿Debo usar dobles en primer lugar? si la precisión es un concepto relevante, entonces el uso de dobles puede ser un error.

b) Si los dobles son apropiados, ¿qué quiero decir con precisión? Si solo está hablando de pantalla, ajuste la lógica en una función de visualización y solo tendrá que tratar con ella en un solo lugar; es decir. aplicar el principio SECO.

Vi la respuesta en la parte superior:

 Double toBeTruncated = new Double("3.5789055"); Double truncatedDouble = BigDecimal.valueOf(toBeTruncated) .setScale(3, RoundingMode.HALF_UP) .doubleValue(); 

que creo que no es la respuesta perfecta. Porque la respuesta cambiará cuando llame a .doubleValue () en muchos casos. Ejemplo: salida de BigDecimal.valueOf (toBeTruncated) .setScale (3, RoundingMode.HALF_UP) es 12.500

luego, después de .doubleValue (), la salida será 12.5, es decir, se perderá la precisión.

La solución usa el tipo BigDecimal sin el método .doubleValue () para mostrar o usar el formato de cadena después de la respuesta final

Tal vez este método lo ayude a precisar valores dobles.

 double truncate(double number) { int integerPart = (int) number; double fractionalPart = number - integerPart; fractionalPart *= 100; //It is for upto two decimal values after point. //You can increase the zeros to fulfill your needs. int fractPart = (int) fractionalPart; fractionalPart = (double) (integerPart) + (double) (fractPart)/100; return fractionalPart; } 

Este método permitirá establecer el nivel de precisión.

 double truncate(double number, int precision) { double prec = Math.pow(10, precision); int integerPart = (int) number; double fractionalPart = number - integerPart; fractionalPart *= prec; int fractPart = (int) fractionalPart; fractionalPart = (double) (integerPart) + (double) (fractPart)/prec; return fractionalPart; } 
 public static String setPrecision(String number, int decimal) { double nbr = Double.valueOf(number); int integer_Part = (int) nbr; double float_Part = nbr - integer_Part; int floating_point = (int) (Math.pow(10, decimal) * float_Part); String final_nbr = String.valueOf(integer_Part) + "." + String.valueOf(floating_point); return final_nbr; }