2012-08-28 16 views
5

El tipo de datos doble no puede representar correctamente algunos valores base 10. Esto se debe a cómo los números de coma flotante representan números reales. Lo que esto significa es que cuando se representan los valores monetarios, se debe usar el tipo de valor decimal para evitar errores. (no dude en corregir errores en este preámbulo)Qué valores no se pueden representar correctamente con un doble

Lo que quiero saber es cuáles son los valores que presentan un problema bajo el tipo de datos doble en una arquitectura de 64 bits en el marco .Net estándar (C# si eso hace una diferencia)?

Espero que la respuesta sea una fórmula o regla para encontrar dichos valores, pero también me gustaría tener algunos valores de ejemplo.

+0

Use decimal al representar valores monetarios, eso es cierto ... y debe seguirse ya sea en 64 bits o 32 bits en arco. – JonH

+0

O centavos (o subcentos) como BigInteger :) – Joey

+0

En cuanto a la especificación de .Net, la arquitectura 64, etc. estaba en caso de que hubiera detalles de implementación que debían tenerse en cuenta para responder mi pregunta. – Gilles

Respuesta

7

Cualquier número que no se pueda escribir como suma de potencias positivas y negativas de 2 no se puede representar exactamente como un número binario de coma flotante.

La común IEEE formats for Las representaciones de 32 y 64 bits de los números de coma flotante imponen restricciones adicionales; limitan el número de dígitos binarios tanto en el significado como en el exponente. De modo que hay números representables máximos y mínimos (aproximadamente +/- 10^308 (base-10) si sirve la memoria) y límites a la precisión de un número que se puede representar. Este límite en la precisión significa que, para números de 64 bits, la diferencia entre el exponente de la mayor potencia de 2 y la más pequeña de un número está limitada a 52, por lo que si su número incluye un término en 2^52, puede también incluye un término en 2^-1.

Los ejemplos simples de números que no se pueden representar exactamente en números binarios de coma flotante incluyen 1/3, 2/3, 1/5.

Dado que el conjunto de números flotantes (en cualquier representación) es finito, y el conjunto de números reales es infinito, un algoritmo para encontrar un número real que no es exactamente representable como un número flotante es seleccionar un número real al azar. La probabilidad de que el número real sea exactamente representable como un número de coma flotante es 0.

+1

Mientras '10^5000' no se puede representar con' double', in se puede representar exactamente como un número binario de coma flotante. – CodesInChaos

1

Esta pregunta va más allá de cualquier lenguaje de programación o plataforma. La inexactitud es en realidad inherente a los datos binarios.

Considere que con un doble, cada número N a la izquierda (en el índice I basado en 0) del punto decimal representa el valor N * 2^I y cada dígito a la derecha del punto decimal representa el valor N * 2^(- I).

Como ejemplo, 5.625 (base 10) sería 101.101 (base 2).

Dado este cálculo, y el valor decimal que no se puede calcular como una suma de 2^(- I) para diferentes valores de I tendría un valor incorrecto como un doble.

+1

Esto simplemente plantea la pregunta. ¿Cómo puedo saber si un valor decimal base 10 particular puede representarse como N * 2^-i para un i finito? – Servy

+0

@Servy: http://cs.furman.edu/digitaldomain/more/ch6/dec_frac_to_bin.htm y muchas otras referencias responden a su pregunta. –

+1

@HighPerformanceMark Luego debe incluir eso en su respuesta. Sin eso, no lo estás ayudando a resolver un problema, solo le estás dando un nuevo problema para resolver. – Servy

1

Por lo general, debe estar preparado para la posibilidad de que cualquier valor que almacene en un double tenga una pequeña cantidad de error. A menos que esté almacenando un valor constante, es posible que sea algo con al menos un error. Si es imperativo que nunca haya ningún error, y los valores no son constantes, probablemente no deba usar un tipo de coma flotante.

Lo que probablemente debería preguntar en muchos casos es, "¿Cómo trato con los pequeños errores de coma flotante?" Querrá saber qué tipos de operaciones pueden generar muchos errores y qué tipos no. Deberá asegurarse de que comparar dos valores para "igualdad" en realidad solo asegura que están "lo suficientemente cerca" en lugar de exactamente igual, etc.

+0

¿Por qué se votó negativamente? ¿No hay nada intrínsecamente incorrecto al respecto? – JonH

+0

@JonH Yo también soy un poco curioso. Supongo que técnicamente no contesté la pregunta, intenté resolver el problema raíz independientemente de la pregunta real. – Servy

+0

Pero su respuesta ayuda a responder la pregunta, la renunciaré pero me temo que esto es algún tipo de represalia, no hay nada de malo en su declaración. – JonH

1

Un flotador se representa como s, e y m en la siguiente fórmula

s * m * 2^e 

Esto significa que cualquier número que no se puede representar utilizando la expresión dada (y en los respectivos dominios de s, e y m) no se puede representar exactamente.

Básicamente, puede representar todos los números entre 0 y 2^53 - 1 multiplicados por una cierta potencia de dos (posiblemente una potencia negativa). Como ejemplo, todos los números entre 0 y 2^53 - 1 se pueden representar multiplicados por 2^0 = 1. Y también puede representar todos esos números dividiéndolos por 2 (con una fracción de .5). Y así.

Esta respuesta no cubre completamente el tema, pero espero que ayude.

Cuestiones relacionadas