2009-04-05 21 views
40

Come determinare se un numero NSN di Cocoa rappresenta NaN (non un numero)?Determinare se NSNumber è NaN

Questo emerge, ad esempio, quando analizzo una stringa con contenuti non numerici non validi.

risposta

61

Quindi, ho scoperto che la proprietà di classe [NSDecimalNumber notANumber] è solo per questo scopo. In alcune lingue NaN! = NaN, ma questo non è il caso di Cocoa.

+40

Solo per chiarezza, per verificare se un NSNumber è NaN allora il codice sarebbe: '[NSNumber isEqualToNumber: [NSDecimalNumber NotANumber]]'. Questo restituisce SÌ se NSNumber è NaN. – SimonB

-2

Non esiste un oggetto di questo tipo per NSNumber poiché se non è un numero, quindi, beh, non è un NSNumber. È più usuale usare un oggetto nullo per rappresentarlo.

15

Come dice Mike Abdullah, il modo naturale per rappresentare un NaN in Cocoa è con nil, ma [NSNumber numberWithDouble:NAN] restituisce un oggetto valido. Non c'è il NSNumber, un modo specifico per rilevare questo, ma il modo generale, isnan([foo doubleValue]), funziona. Se non ti piacciono le funzioni, puoi inserirle in una categoria.

+0

hey guys: Sono abbastanza sicuro che nil non significa la stessa cosa di NaN. Nil significa nessun valore. NaN è usato per rappresentare il risultato di certe operazioni in virgola mobile (dividendo per zero, per esempio) ... quindi in realtà NaN È un numero .. È il numero "Non un numero" ... – nielsbot

+1

Sì, lo sappiamo. Il punto rimane che 'nil' è il modo naturale per rappresentare cose come una stringa con costanti non numeriche, come nell'esempio dell'OP. –

5

c'è anche la funzione isnan() l'ho trovata oggi.

0

Qualsiasi espressione booleana con NaN restituirà sempre false. Ma come è utile?

Stavo recuperando Nan dalla posizioneInView: mentre gestivo alcuni gesti in un'app per iPhone. Ed è stato molto contento di scoprire che qualsiasi espressione booleana con NaN restituirà sempre false. Metto questo per usare liek qui sotto:

// Stavo usando il UIPanGestureRecognizer, e sembra che su TouchUp vorrei ottenere Nan per il/location .x - .y - piuttosto ragionevole dal momento che in questo caso la fine di un tocco non ha una posizione

CGPoint location = [gestureRecognizer locationInView:self]; 

if (location.x != location.x || location.y != location.y) 
{ 
return; 
} 

Allora finché .x e .y o valori float legittimi, ovviamente non saranno mai diverso da lì proprio valore. MA nel caso di .x o .y essendo NaN, il confronto sarà falso. E posso tranquillamente evitare i calcoli con Nan.

10

Per decimali, almeno:

[[NSDecimalNumber notANumber] isEqualToNumber:myNumber] 
6

ho trovato che questo funziona, ma è legale?

NSNumber *NaN = [NSDecimalNumber notANumber]; 

NSDecimalNumber *x = ... fill it somehow with NaN content ... 

if (x == NaN) ... this works 

è NaN garantita per essere un valore costante singleton? Sarebbe bello, ma suppongo che non lo sia, dal momento che tutti gli esempi che ho trovato usano i metodi isEqual.

+0

Certo, nessuna parola 'singleton' nella documentazione, sembra necessario isEqual-ish tutti i controlli. (( – dmitrynikolaev

+0

NaN non è un valore univoco - ci sono varianti, tra cui NaN 'quiet' e 'NaN di segnalazione' e la definizione di codifica consente ad alcuni bit irrilevanti (ad esempio il segno) di avere qualsiasi valore. Per questo motivo == NAN non può essere –

+0

Sicuramente è un singleton dietro le quinte, ma è comunque meglio usare sEqual nel caso in cui questo comportamento cambi in futuro. – Andy

8

Per determinare se NSNumber è un NaN, convertirlo in un doppio e utilizzare la funzione C isnan():

NSNumber *validNumber = [NSNumber numberWithDouble: 1.]; 
NSLog(@"%d", isnan(validNumber.doubleValue)); // prints "0" 

NSNumber *nanNumber = [NSNumber numberWithDouble: 0./0.]; 
NSLog(@"%d", isnan(nanNumber.doubleValue)); // prints "1" 

Tuttavia, si deve fare attenzione, perché ci sono altri valori speciali, ad esempio:

NSNumber *posInfinity = [NSNumber numberWithDouble: 1./0.]; 
NSLog(@"%d", isnan(posInfinity.doubleValue)); // prints "0" 

Se si desidera verificare la presenza di questi valori così, è meglio usare isnormal() invece:

NSLog(@"%d", isnormal(validNumber.doubleValue)); // prints "1" 
NSLog(@"%d", isnormal(nanNumber.doubleValue)); // prints "0" 
NSLog(@"%d", isnormal(posInfinity.doubleValue)); // prints "0" 
+0

Vale la pena notare che 'isnormal (0)' restituisce 0 (come 'isnormal (NAN)') quindi se zero è un valore potenzialmente valido, controlla sia 'inan' che' isinf'. 'isfinite()' è un'opzione migliore. – Demitri

2

Possiamo anche usare un #define definito in matematica.h, nel modo seguente

if(isnan(myNumber)) 
{ // myNumber is NaN . 

}

+1

Questa soluzione funziona con i tipi di dati primitivi e non con gli oggetti NSNumber direttamente, devi ottenere il valore di NSNumber, esempio: number.intValue – ObjSal

Problemi correlati