Mover decimales en un doble

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?

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 

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.

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 

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.

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

Esto es causado por la forma en que las computadoras almacenan números de coma flotante. Ellos no lo hacen exactamente. Como progtwigdor, debe leer esta guía de punto flotante para familiarizarse con las pruebas y tribulaciones del manejo de números de coma flotante.

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.

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

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 .