2010-09-22 11 views
8

Ho appena incontrato questa riga di codice:È se (doppio) C++ valido?

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

dove length2 restituisce un double. È una specie di puzzle che 0.0 sia equivalente a 0, NULL e/o false.

Questa parte dello standard C++ è un comportamento non definito?

+1

Fare attenzione anche a NaN –

risposta

9

Si tratta di un comportamento molto più standard (booleano Conversione)

$ 4,12/1 - "Un rvalue di aritmetica, enumerazione, puntatore o puntatore a tipo membro può essere convertito in un rvalue di type bool. Un valore zero, valore puntatore nullo o membro nullo il valore del puntatore viene convertito in falso; qualsiasi altro valore viene convertito in vero. "

5

Sì - il confronto è contro zero (0.0) e restituisce false se il risultato è esattamente zero e vero altrimenti.

Il comportamento è ereditato da C, che tratta il confronto equivalente nello stesso modo.

0

Quando si effettua il confronto senza operatori, si confronta "contro vero", in modo che ogni tipo di variabile sia selezionato come booleano (caso semplice) o altro. I tipi di variabili numeriche hanno il loro valore falso definito come "0", "0.0" o così, quindi quando li confronti "contro true", il tuo confronto restituirà false.

7

Vale la pena notare che questo codice è estremamente fragile per le rappresentazioni in virgola mobile. Questo codice funzionerà se e solo se il valore in virgola mobile è esattamente 0, che in realtà è piuttosto improbabile nella maggior parte delle circostanze. Potrebbe non essere in questo caso particolare, ma dovrebbe essere certamente documentato/commentato in tal caso.

In praticamente tutte le altre situazioni è necessario decidere su un "epsilon value" che definisce l'intervallo di numeri in virgola mobile che si considerano "uguali", altrimenti è probabile che i propri confronti vi sorprendano in un angolo (e spesso non proprio nell'angolo casi).

+3

+1 per indicare la fragilità del codice. Questo si romperà in molte condizioni che potrebbero non essere ovvie: 'double d = 0.0/-1.0; if (d) 'yields false, come' -0.0! = 0.0', e lo stesso vale per molte altre operazioni che potrebbero produrre una chiusura sufficiente al valore '0' che non è ** esattamente **' 0.0' –

+0

Just to to essere sicuro Potrebbe il codice "double x = 0.0; if (x) {cout <<" x non è nullo ";}" print "x non è nullo"? –

+3

@David Rodríguez - dribeas: No, '-0.0 == 0.0', anche se i modelli di bit sarebbero diversi. Questo è di fondamentale importanza. L'espressione '(x == 0.0 || (1.0/x))' non valuterà '1.0/x' quando ciò causerebbe una divisione per zero. – MSalters

0

Se length2 restituisce 0.0, verrà considerato falso. Ma potresti ottenere risultati sorprendenti con questo confronto. È preferibile utilizzare il valore epsilon come suggerito da MadKeithV durante il confronto in virgola mobile.