Determine if NSNumber is NaN
Asked Answered
B

9

53

How can I determine if a Cocoa NSNumber represents NaN (not a number)?

This emerges, for example, when I parse a string that has an invalid (non-numeric) contents.

Babette answered 5/4, 2009 at 18:24 Comment(0)
B
75

So, I found out that the class property [NSDecimalNumber notANumber] is just for this purpose. In some languages NaN != NaN, but this isn't the case in Cocoa.

Babette answered 5/4, 2009 at 18:33 Comment(1)
Just for clarity, to test if an NSNumber is NaN then the code would be: [NSNumber isEqualToNumber:[NSDecimalNumber notANumber]]. This returns YES if the NSNumber is NaN.Dissentient
S
19

As Mike Abdullah says, the natural way to represent a NaN in Cocoa is with nil, but [NSNumber numberWithDouble:NAN] does return a valid object. There is no NSNumber-specific way of detecting this, but the general way, isnan([foo doubleValue]), works. If you don’t like functions, you can stick it in a category.

Sou answered 6/4, 2009 at 22:15 Comment(2)
hey guys: I'm pretty sure nil doesn't mean the same thing as NaN. Nil means no value at all. NaN is used to represent the result of certain floating point operations (dividing by zero, for example)... so really NaN IS a number.. It's the number "Not A Number"...Kibitz
Yes, we know that. The point remains that nil is the natural way to represent things like a string with non-numeric constants, as in the OP’s example.Sou
M
15

For decimals, at least:

[[NSDecimalNumber notANumber] isEqualToNumber:myNumber]
Mourner answered 5/4, 2009 at 18:24 Comment(0)
Z
12

To determine if NSNumber is a NaN, convert it to a double and use the C function 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"

However, you should be careful, because there are other special values, for example:

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

If you want to check for these values as well, it's better to use isnormal() instead:

NSLog( @"%d", isnormal(validNumber.doubleValue) ); // prints "1"
NSLog( @"%d", isnormal(nanNumber.doubleValue) ); // prints "0"
NSLog( @"%d", isnormal(posInfinity.doubleValue) ); // prints "0"
Zagreb answered 15/11, 2012 at 19:1 Comment(1)
It’s worth noting that isnormal(0) returns 0 (same as isnormal(NAN)), so if zero is a potentially valid value, check both inan and isinf instead. isfinite() is a better option.Selfevident
O
10

I found that this works, but is it legal?

NSNumber *NaN = [NSDecimalNumber notANumber];

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

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

is NaN guaranteeed to be a singleton constant value? Would be cool, but I suppose it is not, since all examples I found use the isEqual methods.

Oraleeoralia answered 3/8, 2012 at 20:22 Comment(3)
Sure, no word 'singleton' in documentation, seems need to isEqual-ish all checks. ((Intrigue
NaN is not a unique value - there are variants, including 'quiet' NaN and 'signaling' NaN, and the encoding definition allows some irrelevant bits (e.g. sign) to have any value. For this reason == NAN cannot be relied upon.Mock
Surely it's singleton behind the scenes, but it's still better to use sEqual in case if this behavior change in future.Aut
A
5

there is also the function isnan() i found it today.

Amnesia answered 21/1, 2010 at 18:21 Comment(0)
B
3

We can also use a #define defined in math.h as follws

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

}

Burnsides answered 4/8, 2014 at 7:20 Comment(1)
This solution works with primitive data types and not with NSNumber objects directly, you have to get the value out of NSNumber, example: number.intValueSunbonnet
K
0

Any Boolean expression with NaN will always return false. But how is that useful?

I was getting Nan back from locationInView: while handling some gestures in an iPhone app. And was very pleased to find that any Boolean expression with NaN will always return false. I put this to use liek below:

//I was using the UIPanGestureRecognizer, and seems that on TouchUp I would get Nan for the /location .x - .y - pretty reasonible since in this case the end of a touch doesnt have a location.

CGPoint location = [gestureRecognizer locationInView:self];

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

So then as long .x and .y or legitimate float values, of course they will never be not equal to there own value. BUT in the case of .x or .y being NaN, the comparison will be false. And I can safely avoid computations with Nan.

Knapweed answered 25/10, 2010 at 19:8 Comment(0)
C
-3

There isn't really such an object for NSNumber since if it's not a number, then, well, it's not an NSNumber. It's more usual to use a nil object to represent this.

Creatinine answered 6/4, 2009 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.