2011-11-14 10 views
5

En C:misma condición en C y Java, diferente resultado

float a = 1.3; 
if (a == 1.3) 
    printf("Hello c"); 
else 
    printf("Bye c"); 

//output: Bye c 

En Java:

float a = 1.3; 
if (a == 1.3) 
    System.out.println("Hello java"); 
else 
    System.out.println("Bye java"); 

//output: Hello java 

¿Por qué es esto así?

+2

I ' he hecho varias [pequeñas correcciones] (http://programmers.stackexchange.com/posts/119596/revisions) en su código, no había manera de que su código original funcionara. ¿Has visto tu código producir la salida o acabas de copiarlo de alguna parte? – yannis

Respuesta

21

No se puede representar exactamente "1.3" como un flotador binario.

La conversión del literal 1.3 en un flotador dará como resultado un número de coma flotante que está cerca pero no exactamente igual a 1.3.

En el caso de Java tuvo suerte porque la JVM interpreta el "1.3" como un flotador estándar de Java y lo convierte casi en 1.3. número binario. En el caso C, el estándar dice que 1.3 debe interpretarse como un "doble" y lo convierte en un punto flotante binario que está un poco más cerca del valor decimal 1.3 que el float ordinario.

La conclusión es que nunca se deben comparar los flotadores por igualdad ya que las pequeñas variaciones en el almacenamiento, el orden de cálculo, etc. producirán resultados ligeramente diferentes. Siempre se debe "soporte" cualquier comparación de flotación de este modo:

if (a > 1.299 && a < 1.301) // something close to 1.3 
+7

Solo para ser una elección completa: en C, '1.3' siempre es un doble. La sintaxis para los literales de flotación (de precisión simple) es '1.3f'. – tdammers

+0

@tdammmers - gracias. No estaba seguro de si esto era específico del compilador u obligatorio por el estándar. –

1

sólo para ayudar a envolver su cerebro alrededor de la respuesta, te voy a dar una simple analogía. Recuerde que los números de coma flotante son aproximados. Muchos números no pueden representarse exactamente. Ahora, imagine que hacemos lo mismo con decimales, digamos que usamos seis dígitos después del lugar decimal.

¿Cómo representamos 1/3? .333333 es lo mejor que podemos hacer. Pero ahora 3 * 1/3 no será igual a 1.

¿Cómo representamos 2/3? .666666 al menos garantizará 2 * 1/3 = 2/3. Pero 2/3 + 1/3 no será igual a 1.

Podemos representar 2/3 como .666667. Pero entonces 2 * 1/3 no será igual a 2/3. Pero al menos 1/3 + 2/3 será igual a uno.

De modo que el punto es que, con representaciones aproximadas, no puede garantizar respuestas exactamente correctas, solo respuestas suficientemente cercanas. En general, nunca debe comparar los números de punto flotante para la igualdad a menos que sea 100% positivo de que comprenda lo que está haciendo y por qué.

0

Lo primero que se debe saber con respecto a C es que es muy incorrecto probar 2 números de punto flotante para la igualdad debido a la implementación de los números de punto flotante por el compilador. '1.3' cuando se almacena en una variable flotante, no ha rellenado todos los decimales a los que almacena el compilador y es probable que se llenen con algunos dígitos dando lugar a la falla de la prueba de igualdad

Cuestiones relacionadas