2010-03-11 19 views
18

(int)(33.46639 * 1000000) devuelve 33466389¿Por qué (int) (33.46639 * 1000000) devuelve 33466389?

¿Por qué sucede esto?

+0

¿Qué espera que suceda? – SLaks

+0

@Slaks: 3346639, alias, la respuesta correcta. –

+0

Buen lugar para comenzar: http://docs.sun.com/source/806-3568/ncg_goldberg.html (¿Qué debería saber cada científico informático sobre la aritmética de coma flotante?) – mjv

Respuesta

31

Las matemáticas de punto flotante no son perfectas. What every programmer should know al respecto.

aritmética de punto flotante se considera un tema esotérico por muchas personas. Esto es bastante sorprendente porque el punto flotante es omnipresente en los sistemas informáticos. Casi todos los idiomas tienen un tipo de datos de coma flotante; las computadoras de las PC a las supercomputadoras tienen aceleradores de coma flotante; se recurrirá a la mayoría de los compiladores para compilar algoritmos de coma flotante de vez en cuando; y prácticamente todos los sistemas operativos deben responder a las excepciones de coma flotante como el desbordamiento. Este artículo presenta un tutorial sobre aquellos aspectos de punto flotante que tienen un impacto directo en los diseñadores de sistemas informáticos. Comienza con el fondo sobre la representación de punto flotante y el error de redondeo, continúa con una discusión del estándar de punto flotante IEEE y concluye con numerosos ejemplos de cómo los constructores de computadoras pueden soportar mejor el punto flotante.

...

Exprimir un número infinito de números reales en un número finito de bits requiere una representación aproximada. Aunque hay infinitos enteros, en la mayoría de los programas el resultado de los cálculos enteros se puede almacenar en 32 bits. Por el contrario, dado un número fijo de bits, la mayoría de los cálculos con números reales producirán cantidades que no se pueden representar exactamente utilizando tantos bits. Por lo tanto, el resultado de un cálculo de punto flotante a menudo debe redondearse para volver a su representación finita. Este error de redondeo es la característica del cálculo en coma flotante.

+1

Es cierto que la aritmética de punto flotante es omnipresente y complicada, pero esto no responde a la pregunta (a menos que cuente el enlace a un documento de 80 páginas que tiene la respuesta en alguna parte). –

+2

@Henry: el punto está en el título del artículo vinculado. ** Cada ** programador debe saber sobre esto, y si no lo hacen deben leer el artículo. (OK, tal vez no todas las 80 páginas ...) –

+9

+1: el enlace a un documento de 80 páginas que tiene la respuesta en alguna parte es el estándar. Esta pregunta, de una forma u otra, se pregunta con demasiada frecuencia. Este documento es * la * respuesta. Las preguntas son todas duplicadas.No necesitamos repetir esta información una y otra vez. –

5

doble precisión no es exacta, por lo que internamente 33.46639 se almacena realmente tan 33,466389

Edit: Como dijo Richard, está flotando datos de puntos, (almacenados en binario en un conjunto finito de bits) así que no es exactamente eso) ....

+1

o 33.4668885 o algo más "lo suficientemente cerca" como para redondear, dependiendo del hardware. – DaveE

+1

Um, ninguna de las anteriores. Está en la base 2. La mayoría de esos números NO PUEDEN expresarse exactamente en la base 10. (Sin recurrir a secuencias de dígitos que se repiten infinitamente, de todos modos. Similar a cómo 1/3 se debe representar como 0.33333 [inf] en la base 10.) –

+0

, no exactamente eso ... pero algo más cercano a eso que el original. –

-1

La razón por la que tiene un resultado diferente es el hecho de que utilizó un 'fundido '

 
(int)(33.46639 * 1000000) returns 33466389 
^^^^^ 

a emitir el resultado a un tipo de 'int' ... hasta que, o bien redondeado o hacia abajo el tipo integral cuando multiplicada juntos y luego se convierte en 'int' .... no se basan en coma flotante a ser lo suficientemente precisa .... Skeet registró una excelente introducción en su sitio here y here ...

+0

No hay nada intrínsecamente negativo en un reparto. Existen bibliotecas de precisión arbitraria. –

+0

Me imagino que está preguntando "¿de dónde salieron los 8 en mi resultado?" Multiplicar por 1000000 es como mover el decimal 6 lugares a la derecha, que debería ser "33466390", pero eso no es lo que está obteniendo. Sin embargo, su respuesta es lo que inicialmente pensé, hasta que vuelva a leer la pregunta. – Pwninstein

+0

@Richard - forzar un valor 'float' o' double' a un 'int' descarta la parte fraccional, por lo que se pierde información. – Seth

1

Si está preguntando por qué no lo hace convertirse en 33466390, es porque double s no tienen una precisión infinita, y el número no se puede expresar exactamente en binario.

Si reemplaza el double con un decimal ((int)(33.46639m * 1000000)), que sea igual a 33466390, porque decimal s se calculan en base 10.

+0

Problemas como estos son inherentes al punto flotante, no solo al punto flotante binario. Claro, el decimal obtiene 33.46639 * 1000000 a la derecha, pero todavía tiene 1/3 * 3! = 1 y pow (sqrt (2), 2)! = 2. – dan04

+0

Sí, pero su problema específico se debe a los binarios. – SLaks

2

La razón es que 33.46639 serán representados como algo ligeramente menor que el número de .

Multiplicar por 1000000 le dará 33466389.99999999.

El moldeado de texto con (int) simplemente devuelve la parte entera (33466389).

Si desea el número "correcto", intente redirigir() antes de escribir el texto.

+4

¡Whoa! ..... no no no no no. Si desea la respuesta "correcta", no puede usar la aritmética de punto flotante. –

+4

No. Si desea la respuesta "correcta", no puede usar la aritmética de coma flotante * binario *. Use el tipo 'decimal' que usa la aritmética de coma flotante decimal y funcionará como espera. – Gabe

+1

33.46639 es la respuesta "correcta". El problema es que el interlocutor no hace la pregunta correcta. –

1

Porque 33.46639 no se puede expresar exactamente en un número finito de dígitos binarios. El resultado real de 33.46639 * 1000000 es 33466389.9999999962747097015380859375. El reparto lo trunca en 33466389.

+0

Probar "no se puede expresar exactamente en un número finito de dígitos binarios fraccionarios" –

3

Era la víspera de Año Nuevo a finales de 1994. Andy Grove, CEO de Intel, venía de un gran año, con el procesador Pentium siendo un gran éxito. Entonces, entró a un bar y pidió una toma doble de Johnnie Walker Green Label.

El cantinero lo sirvió y dijo: "eso será $ 20, señor".

Grove colocó un billete de veinte dólares en el mostrador, lo miró por un momento y dijo: "mantén el cambio".

http://en.wikipedia.org/wiki/Pentium_FDIV_bug

+0

Pero ... eso es un número entero ... – Rawling

Cuestiones relacionadas