2010-09-20 13 views
10

Esto es lo que sucede en mi equipo:¿Por qué es (doble) 0.6f> (doble) (6/10f)?

(double)(float)0.6 
= 0.60000002384185791 

(double)0.6f 
= 0.60000002384185791 

(double)(6/10f) 
= 0.6 

(double)(float)(6/10f) 
= 0.6 

6/10f es también un flotador, ¿cómo es que puede ser, precisamente, 0,6?
En mi opinión (doble) (6/10f) también debería ser 0.60000002384185791. ¿Alguien puede ayudar a explicar esto? ¡Gracias!

+0

Por cierto en Java, el resultado es 0.6000000238418579 para todo lo anterior. –

+0

Estoy usando ventana inmediata. He probado en el programa, no son iguales.Entonces no es una cuestión de foramtting. – zhy2002

+0

http://stackoverflow.com/questions/1778368/python-float-str-float-weirdness – Sharun

Respuesta

5

En primer lugar, es importante tener en cuenta que 0.6 no se puede representar con precisión como float sin embargo, puede son representados con precisión como un double (las inexactitudes de la aritmética de coma flotante están bien documentados, si no está claro por qué 0.6 no puede se representa con precisión como un flotador, prueba this link)

La razón por la que estás viendo el comportamiento anterior es responsabilidad del compilador: si echas un vistazo al conjunto compilado en el reflector, entonces lo que está sucediendo aquí es un poco más claro:

(ACTUALIZACIÓN he cambiado el código para que no utiliza Console.WriteLine, mientras me daba cuenta de que el compilador estaba eligiendo una sobrecarga para usted, que confunde la situación)

// As written in source 
var j = (double)(float)0.6; 
var k = (double)0.6f; 
var l = (double)(6/10f); 
var m = (double)(float)(6/10f); 

// Code as seen by Reflector 
double j = 0.60000002384185791; 
double k = 0.60000002384185791; 
double l = 0.6; 
double m = 0.6; 

Por qué el compilador decide compilar de esta manera en particular es más allá de mí (FYI, esto es todo con optimizaciones desactivadas)

Algunos otros casos interesantes:

// Code 
var a = 0.6; 
var b = (double)0.6; 
var c = 0.6f; 
var d = (float)0.6; 

var e = 6/10; 
var f = 6/(10f); 
var g = (float)(6/10); 
var h = 6/10f; 
var i = (double)6/10; 
// Prints out 0.60000002384185791 

double n = (float)0.6; 
double o = f; 

// As seen by Reflector 
double a = 0.6; 
double b = 0.6; 
float c = 0.6f; 
float d = 0.6f; 

int e = 0; 
float f = 0.6f; 
float g = 0f; 
float h = 0.6f; 
double i = 0.6; 

double n = 0.60000002384185791; 
double o = f; 

el compilador sólo parece hacer el ab Oye, engaña en un par de casos especiales, ¿por qué solo hace esto cuando lanzar a un doble está completamente más allá de mí?

El resto del tiempo parece hacer algún truco para hacer que la aritmética de punto flotante parezca para funcionar donde, de hecho, normalmente no sería así.

+0

Curiosamente, si utiliza 'float', todos ellos imprimirán 0.6 (como se ve en [ideone] (http://ideone.com/2lvBI), también probado con Visual C#) – NullUserException

+0

Gracias a todos, creo que es de hecho un problema específico del compilador. – zhy2002

+0

También encontré que: float float3 = 0.6f; int int1 = 6; float1 = 10; Assert.IsTrue (int1/float1> = float3); // falla, en mi código float3 es un argumento! – zhy2002

2

Parece que está redondeando el resultado. ¿Estás mostrando el resultado con los dígitos de precisión necesarios? Puede usar this c# class de Jon Skeet para obtener la representación numérica exacta del resultado impreso.

Tenga en cuenta que no siempre ToString() imprimirá todos los dígitos, ni el depurador de Visual Studio.

1

Si yo fuera un hombre de apuestas, yo diría que la diferencia está en que la coerción está sucediendo. En los dos últimos ejemplos (los que tienen 6/10f), hay dos literales que son ambos números enteros (el entero 6 y el flotante 10.00000000 ...). La división parece estar sucediendo después de la coerción, al menos en el compilador que está utilizando. En los dos primeros ejemplos, tiene un literal flotante fraccionario (0.6) que no se puede expresar adecuadamente como un valor binario dentro de la mantisa de un flotador. Coaccionar ese valor a un doble no puede reparar el daño que ya se hizo.

En los entornos que están produciendo resultados completamente consistentes, la división se produce antes de que la coerción se duplique (el 6 se forzará a un flotador para que la división coincida con el 10, la división se lleva a cabo en espacio flotante, luego el resultado es forzado a un doble).

+0

Siempre puede tomarse un abucheo con lo que sucedió usando ildasm y mirando el conjunto intermedio creado. –

Cuestiones relacionadas