确定NSNumber是否为NaN

53

如何确定Cocoa中的NSNumber是否表示NaN(非数字)?

例如,当我解析一个包含无效(非数值)内容的字符串时会出现这种情况。

9个回答

75

所以,我发现类属性 [NSDecimalNumber notANumber] 就是为了这个目的。在某些语言中,NaN!= NaN,但在Cocoa中不是这种情况。


46
为了明确,要测试一个NSNumber是否为NaN,则代码应为:[NSNumber isEqualToNumber:[NSDecimalNumber notANumber]]。如果NSNumber是NaN,则这将返回YES。 - SimonB

19

如Mike Abdullah所说,Cocoa中表示NaN的自然方式是使用nil,但[NSNumber numberWithDouble:NAN]确实会返回一个有效的对象。没有NSNumber特定的方法来检测这一点,但通用的方法isnan([foo doubleValue])可以工作。如果您不喜欢函数,您可以把它放在一个类别中。


嘿,大家好:我非常确定 nil 和 NaN 的含义不同。Nil 表示根本没有值。NaN 用于表示某些浮点运算的结果(例如除以零)……所以实际上 NaN 是一个数字。它是“不是数字”的数字…… - nielsbot
1
是的,我们知道。重点在于nil 是表示像OP例子中带有非数字常量的字符串的自然方式。 - Jens Ayton

15

对于小数,至少:

[[NSDecimalNumber notANumber] isEqualToNumber:myNumber]

12

要确定NSNumber是否为NaN,请将其转换为double,并使用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"

但是,你需要小心,因为还有其他特殊的值,例如:

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

如果您希望检查这些值,最好使用isnormal()

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

值得注意的是 isnormal(0) 返回 0(与 isnormal(NAN) 相同),所以如果零是一个可能有效的值,请同时检查 inanisinf。使用 isfinite() 更好。 - Demitri

10

我发现这个方法可行,但是它是否合法?

NSNumber *NaN = [NSDecimalNumber notANumber];

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

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

NaN是否保证是一个singleton常量值?这样会很酷,但我认为并不是这样,因为我找到的所有例子都使用了isEqual方法。


当然,在文档中没有“singleton”一词,似乎需要进行isEqual-ish所有检查。 - dmitrynikolaev
NaN不是唯一的值 - 它存在多种变体,包括“静默”NaN和“信令”NaN,并且编码定义允许某些无关位(例如符号)具有任何值。因此,不能依赖== NAN。 - Alex Brown
虽然在幕后它是单例模式,但为了防止将来的行为更改,最好还是使用sEqual。 - pronebird

5

还有一个函数isnan(),我今天发现了它。


3
我们也可以使用math.h中的#define,如下所示。
if(isnan(myNumber))
{  // myNumber is NaN .

}


1
这个解决方案适用于原始数据类型,而不是直接使用NSNumber对象,你必须从NSNumber中获取值,例如:number.intValue。 - ObjSal

0

任何带有NaN的布尔表达式都将始终返回false。但这有什么用呢?

在处理iPhone应用程序中的某些手势时,我从locationInView:中得到了NaN。很高兴发现任何带有NaN的布尔表达式都将始终返回false。我像下面这样使用它:

//我正在使用UIPanGestureRecognizer,似乎在TouchUp时我会得到/location .x - .y的Nan - 在这种情况下,触摸结束没有位置,所以这是相当合理的。

CGPoint location = [gestureRecognizer locationInView:self];

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

因此,只要.x和.y是合法的浮点值,它们永远不会与自己的值不相等。但是,在.x或.y为NaN的情况下,比较将为false。我可以安全地避免使用NaN进行计算。


-3

实际上,NSNumber 并没有这样的对象,因为如果它不是一个数字,那么它就不是 NSNumber。更常见的做法是使用 nil 对象来表示这个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接