round - redondear decimales en java netbeans
Mover decimales en un doble (9)
Así que tengo un doble juego para que sea igual a 1234, quiero mover un lugar decimal para hacerlo 12.34
Entonces para hacer esto multiplico .1 a 1234 dos veces, algo así como esto
double x = 1234;
for(int i=1;i<=2;i++)
{
x = x*.1;
}
System.out.println(x);
Esto imprimirá el resultado, "12.340000000000002"
¿Hay alguna manera, sin simplemente formatearlo en dos decimales, de tener el doble almacenamiento 12.34 correctamente?
En el software financiero, es común usar enteros por centavos. En la escuela, nos enseñaron cómo usar punto fijo en lugar de flotar, pero eso usualmente es potencias de dos. También puede llamarse "punto fijo" el almacenamiento de centavos en enteros.
int i=1234;
printf("%d.%02d/r/n",i/100,i%100);
En clase, se nos preguntó en general qué números pueden representarse exactamente en una base.
Para base=p1^n1*p2^n2
... puede representar cualquier N donde N = n * p1 ^ m1 * p2 ^ m2.
Let base=14=2^1*7^1
... puedes representar 1/7 1/14 1/28 1/49 pero no 1/3
Conozco el software financiero: convertí los informes financieros de Ticketmaster de VAX asm a PASCAL. Tenían su propio formatln () con códigos por centavos. El motivo de la conversión era que los enteros de 32 bits ya no eran suficientes. +/- 2 billones de centavos son $ 20 millones y eso se desbordó para la Copa Mundial o las Olimpiadas, lo olvidé.
Juré guardar el secreto. Oh bien. En academea, si es bueno publicas; en la industria, lo mantienes en secreto.
Es curioso que numerosas publicaciones mencionen el uso de BigDecimal, pero nadie se molesta en dar la respuesta correcta basada en BigDecimal. Porque incluso con BigDecimal, aún puede salir mal, como lo demuestra este código
String numstr = "1234";
System.out.println(new BigDecimal(numstr).movePointLeft(2));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal(0.01)));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal("0.01")));
Da esta salida
12.34
12.34000000000000025687785232264559454051777720451354980468750
12.34
El constructor de BigDecimal menciona específicamente que es mejor usar un constructor de cadenas que un constructor numérico. La máxima precisión también está influenciada por el MathContext opcional.
Según BigDecimal Javadoc , es posible crear un BigDecimal que es exactamente igual a 0.1, siempre que use el constructor String.
Esto es causado por la forma en que las computadoras almacenan números de coma flotante. Ellos no lo hacen exactamente. Como programador, debe leer esta guía de punto flotante para familiarizarse con las pruebas y tribulaciones del manejo de números de coma flotante.
No - si desea almacenar valores decimales con precisión, use BigDecimal
. double
simplemente no puede representar exactamente un número como 0.1, como tampoco puede escribir el valor de un tercero exactamente con un número finito de dígitos decimales.
No, como los tipos de punto flotante de Java (de hecho, todos los tipos de punto flotante) son un equilibrio entre el tamaño y la precisión. Si bien son muy útiles para muchas tareas, si necesita precisión arbitraria, debe usar BigDecimal
.
Sí hay. Con cada operación doble, puede perder precisión pero la cantidad de precisión difiere para cada operación y puede minimizarse eligiendo la secuencia correcta de operaciones. Por ejemplo, al multiplicar un conjunto de números, lo mejor es ordenarlos por exponente antes de multiplicarlos.
Cualquier libro decente sobre el crujido de números describe esto. Por ejemplo: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Y para responder a tu pregunta:
Usa dividir en lugar de multiplicar, de esta forma obtienes el resultado correcto.
double x = 1234;
for(int i=1;i<=2;i++)
{
x = x / 10.0;
}
System.out.println(x);
Si usa double
o float
, debería usar el redondeo o esperar ver algunos errores de redondeo. Si no puede hacer esto, use BigDecimal
.
El problema que tiene es que 0.1 no es una representación exacta, y al realizar el cálculo dos veces, está agravando ese error.
Sin embargo, 100 se pueden representar con precisión, así que intente:
double x = 1234;
x /= 100;
System.out.println(x);
que imprime:
12.34
Esto funciona porque Double.toString(d)
realiza una pequeña cantidad de redondeo en su nombre, pero no es mucho. Si se pregunta cómo sería sin redondear:
System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));
huellas dactilares:
0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375
En resumen, el redondeo es inevitable para respuestas sensatas en coma flotante, ya sea que lo hagas explícitamente o no.
Nota: x / 100
x * 0.01
no son exactamente iguales cuando se trata de error de redondeo. Esto se debe a que el error de redondeo para la primera expresión depende de los valores de x, mientras que el 0.01
en el segundo tiene un error de redondeo fijo.
for(int i=0;i<200;i++) {
double d1 = (double) i / 100;
double d2 = i * 0.01;
if (d1 != d2)
System.out.println(d1 + " != "+d2);
}
huellas dactilares
0.35 != 0.35000000000000003
0.41 != 0.41000000000000003
0.47 != 0.47000000000000003
0.57 != 0.5700000000000001
0.69 != 0.6900000000000001
0.7 != 0.7000000000000001
0.82 != 0.8200000000000001
0.83 != 0.8300000000000001
0.94 != 0.9400000000000001
0.95 != 0.9500000000000001
1.13 != 1.1300000000000001
1.14 != 1.1400000000000001
1.15 != 1.1500000000000001
1.38 != 1.3800000000000001
1.39 != 1.3900000000000001
1.4 != 1.4000000000000001
1.63 != 1.6300000000000001
1.64 != 1.6400000000000001
1.65 != 1.6500000000000001
1.66 != 1.6600000000000001
1.88 != 1.8800000000000001
1.89 != 1.8900000000000001
1.9 != 1.9000000000000001
1.91 != 1.9100000000000001
puedes intentar la representación de números enteros
int i =1234;
int q = i /100;
int r = i % 100;
System.out.printf("%d.%02d",q, r);
si solo está formateando, prueba printf
double x = 1234;
for(int i=1;i<=2;i++)
{
x = x*.1;
}
System.out.printf("%.2f",x);
salida
12.34