2010-02-06 9 views
7

Duplicar posibles:
Why is floating point arithmetic in C# imprecise?resultado extraño cuando se duplica restando

he estado tratando con algunos números y C#, y la siguiente línea de resultados de código en un número diferente de lo que cabría esperar:

double num = (3600.2 - 3600.0); 

Esperaba que num fuera 0.2, sin embargo, resultó ser 0.1999999999998181. ¿Hay alguna razón por la cual está produciendo un decimal cercano, pero diferente?

+0

Huh, lo mismo aquí. No es tu máquina – tsilb

+2

http://stackoverflow.com/questions/1498296/net-problem-with-subtracting-double-values ​​ –

+2

http://stackoverflow.com/questions/753948/why-is-floating-point-arithmetic-in-c -imprecise –

Respuesta

10

Esto es porque double es un tipo de datos de coma flotante.

Si desea una mayor precisión, puede cambiar al uso de decimal en su lugar.

El sufijo es literal para decimal m, por lo que utilizar decimal aritmética (y produzca un resultado decimal) podría escribir el código como

var num = (3600.2m - 3600.0m); 

Nota que hay desventajas en el uso de un decimal. Es un tipo de datos de 128 bits en comparación con 64 bits, que tiene el tamaño de double. Esto hace que sea más caro tanto en términos de memoria y procesamiento. También tiene un rango mucho más pequeño que double.

+2

Esto no tiene nada con la precisión que tienes (a menos que tengas una precisión infinita, por supuesto). Es la conversión de una base a otra lo que crea esto. – AraK

+6

¿Cuándo se detendrá la información incorrecta sobre los tipos IEEE 754? ¡No es un tipo impreciso! Es un tipo exacto, pero solo puede representar un rango limitado de números. Todos los números no representados exactamente son aproximados, y esta es la causa de los errores. Si desea expresar solo potencias de dos, dentro del rango del tipo, nunca perderá precisión con un punto flotante. – codekaizen

+1

@AdamRalph - eso no es cierto acerca de Decimal, también. System.Decimal es un tipo de punto flotante, pero está en la base 10, por lo que se aplica la base aritmética de base 10. Sin embargo, intente calcular con 1/3, y Decimal perderá precisión, aunque con la mantisa de 96 bits, será una pérdida mucho menor que System.Double. – codekaizen

0

cambiar el tipo de decimal:

decimal num = (3600.2m - 3600.0m); 

También debería leer this.

1

Hay una razón.

La razón es que la forma en que se almacena el número en la memoria, en el caso del tipo de datos dobles, no permite una representación exacta del número 3600.2. Tampoco permite una representación exacta del número 0.2.

0.2 tiene una representación infinita en binario. Si desea almacenarlo en la memoria o en los registros del procesador, para realizar algunos cálculos, en su lugar, se almacena un número cercano a 0.2 con representación finita. Puede no ser evidente si ejecuta código como este.

double num = (0.2 - 0.0); 

Esto es porque en este caso, todos los dígitos binarios disponibles para la representación de los números en el tipo de datos doble se utilizan para representar la parte fraccionaria del número (sólo hay la parte fraccionaria) y la precisión es mayor. Si almacena el número 3600.2 en un objeto de tipo doble, algunos dígitos se utilizan para representar la parte entera - 3600 y hay menos dígitos que representan la parte fraccionaria. La precisión es más baja y la parte fraccionaria que de hecho está almacenada en la memoria difiere de 0.2 lo suficiente, que se vuelve aparente después de la conversión de doble a cadena

Cuestiones relacionadas