2010-09-22 16 views
8

Me acabo de encontrar con esta línea de código:¿Es válido (doble) C++?

if(lineDirection.length2()){...} 

donde length2 devuelve un double. Me desconcierta que 0.0 es equivalente a 0, NULL y/o false.

¿Es esto parte del estándar C++ o es un comportamiento indefinido?

+1

También tenga cuidado con NaN –

Respuesta

9

Es un comportamiento mucho Estándar (booleano conversión)

$ 4,12/1 - "Un valor p de la aritmética, enumeración, puntero, o puntero a tipo de miembro se puede convertir en un rvalue de escriba bool. Un valor cero, valor de puntero nulo, o nulo miembro el valor del puntero se convierte en falso; cualquier otro valor se convierte en verdadero. "

5

Sí, la comparación es contra cero (0.0) y devuelve falso si el resultado es exactamente cero y verdadero de lo contrario.

El comportamiento se hereda de C, que trata la comparación equivalente de la misma manera.

0

Cuando compara sin operadores, está comparando "contra verdadero", por lo que se comprueba que cada tipo de variable sea booleano (caso simple) u otro. Los tipos de variables numéricas tienen su valor falso definido como "0", "0.0" más o menos, por lo que cuando los compara "contra verdadero", su comparación dará como resultado falso.

7

Vale la pena señalar que este código es extremadamente frágil para las representaciones de coma flotante. Este código funcionará si y solo si el valor del punto flotante es exactamente 0, que en realidad es bastante improbable en la mayoría de las circunstancias. Puede que no sea en este caso particular, pero ciertamente debe ser documentado/comentado si es así.

En prácticamente todas las demás situaciones necesita decidir sobre un "epsilon value" que define el rango de números flotantes que considera "lo mismo"; de lo contrario, es muy probable que sus comparaciones le sorprendan en la esquina (y a menudo no tan) casos.

+3

+1 para señalar la fragilidad del código. Esto se romperá en muchas condiciones que pueden no ser obvias: 'doble d = 0.0/-1.0; if (d) 'arroja false, como' -0.0! = 0.0', y lo mismo ocurre con muchas otras operaciones que pueden producir un valor lo suficientemente cercano a '0' que no es ** exactamente **' 0.0' –

+0

Solo para estar seguro. ¿Podría el código "doblar x = 0.0; si (x) {cout <<" x no es nulo ";}" imprimir "x no es nulo"? –

+3

@David Rodríguez - dribeas: No, '-0.0 == 0.0', incluso si los patrones de bits difieren. Esto es críticamente importante. La expresión '(x == 0.0 || (1.0/x))' _no_ evaluará '1.0/x' cuando eso causaría una división por cero. – MSalters

0

Si length2 devuelve 0.0, se tomará como falso. Pero puede obtener resultados sorprendentes con esta comparación. Mejor uso del valor épsilon como MadKeithV sugerido durante la comparación en coma flotante.