Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone NSNumber比较:返回不同的结果_Iphone_Objective C_Nsnumber - Fatal编程技术网

Iphone NSNumber比较:返回不同的结果

Iphone NSNumber比较:返回不同的结果,iphone,objective-c,nsnumber,Iphone,Objective C,Nsnumber,我试着做一些数字比较,我得到了一些奇怪的结果 NSNumber* number1 = [NSNumber numberWithFloat:1.004]; NSNumber* number2 = [NSNumber numberWithDouble:1.004]; ([number1 compare:number2] == NSOrderedSame) ? NSLog(@"YES") : NSLog(@"NO"); ([number1 compare:number2] == NSOrderedA

我试着做一些数字比较,我得到了一些奇怪的结果

NSNumber* number1 = [NSNumber numberWithFloat:1.004];
NSNumber* number2 = [NSNumber numberWithDouble:1.004];

([number1 compare:number2] == NSOrderedSame) ? NSLog(@"YES") : NSLog(@"NO");
([number1 compare:number2] == NSOrderedAscending) ? NSLog(@"YES") : NSLog(@"NO");
([number1 doubleValue] == [number2 doubleValue]) ? NSLog(@"YES") : NSLog(@"NO");
([number1 floatValue] == [number2 floatValue]) ? NSLog(@"YES") : NSLog(@"NO");
日志输出:





这让我非常沮丧。我知道这可能是因为浮点数与双精度浮点数之间的差异。在我看来,这似乎是将double向下截断为float来进行比较。但是如果我不知道这个数字是如何产生的,我如何得到正确的结果呢?是否有其他方法来比较NSNumber?

比较:方法遵循标准C规则进行类型转换。例如,如果将具有整数值的NSNumber对象与具有浮点值的NSNumber对象进行比较,则整数值将转换为浮点值进行比较

此外,使用浮点初始化NSNumber,然后将其转换为double会损失一些精度

NSNumber* number1 = [NSNumber numberWithFloat:1.004];
NSNumber* number2 = [NSNumber numberWithDouble:1.004];
NSLog(@"number1 double: %1.16f", [number1 doubleValue]);
NSLog(@"number2 double: %1.16f", [number2 doubleValue]);
NSLog(@"number1 objCType %s", [number1 objCType]);
NSLog(@"number2 objCType %s", [number2 objCType]);

2012-02-09 15:59:49.487 testNSNumber[89283:f803] number1 double: 1.0039999485015869
2012-02-09 15:59:49.488 testNSNumber[89283:f803] number2 double: 1.0040000000000000
2012-02-09 16:21:01.655 testNSNumber[4351:f803] number1 objCType f
2012-02-09 16:21:01.656 testNSNumber[4351:f803] number2 objCType d
如果您知道可能会混合使用float和double,那么一种解决方案是像您在问题代码段的最后一行中那样比较NSNumber floatvalue


此外,您还可以使用objCType方法获取NSNumber中的数据类型。

请尝试使用
isEqualToNumber
:方法检查您的条件

([number1 isEqualToNumber:number2]) ? NSLog(@"YES") : NSLog(@"NO");

也给出了一个详细的答案

我尝试使用了
isEqualToNumber:
,它返回了否。它们不一样的原因是1.004不能用二进制精确表示。
double
近似值在小数点后的位数比
float
近似值多,因此这两个数字是不同的。通常,在比较浮点数时,您会测试它们是否等于某个公差值
fabs(a-b)

NSNumber* number1 = [NSNumber numberWithFloat:1.004];
NSNumber* number2 = [NSNumber numberWithDouble:1.004];

NSLog(@"number 1: %.12f", [number1 doubleValue]);
NSLog(@"number 2: %.12f", [number2 doubleValue]);

([number1 isEqualToNumber:number2]) ? NSLog(@"YES") : NSLog(@"NO");
fabs([number1 floatValue] - [number2 doubleValue]) < 1.0e-7 ? NSLog(@"YES") : NSLog(@"NO");

另一个对我有效的解决方案是将它们转换为NSString并进行字符串比较。这是因为我使用的是4位数的十进制价格,这对我很有效

-(BOOL) hasPriceChanged{
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    formatter.numberStyle = NSNumberFormatterDecimalStyle;
    formatter.maximumFractionDigits = 4;
    NSString *p = [formatter stringFromNumber:self.price];
    NSString *op = [formatter stringFromNumber:self.originalPrice];
    return ![p isEqualToString:op];
}
这就解决了我比较双精度与2个尾随零和浮点与零的问题


我通常会警告不要进行这样的字符串比较,但由于我的规则一直是固定的,所以在这种情况下对我来说没有问题。

如果您使用
[number1 isEqualToNumber:number2]
,这是首选的方法,至少如果您只是试图确定值的相等性的话?对不起,twilson,这仍然返回否。数字不同。这将无法按预期工作,并将记录为“否”。用浮点和双精度初始化的NSNumbers将是不同的值。见上面我的答案。你提到的问题是使用所有浮动。我真的很喜欢这个对象类型!非常感谢。非常好的解决方案!在我看来,苹果公司不使用compare:method来处理这个问题似乎很疯狂……苹果公司(或者更准确地说,编译器编写人员)不能假设程序员对等式的容忍度。他们所能做的就是程序员让他们做的事情。在本例中,您正在比较两个不相等的值。浮点数不是一个简单的问题。如果您有时间,请看一下。谢谢您的参考!我一直在寻找这方面的推荐读物。我知道这个问题已经有一段时间了,只是还没有采取任何措施。:)这是正确的解决方案,但我要补充的是,通过将该简单算法捆绑到类类别中的-[NSNumber isEqualToNumber:withTolerance:]方法中,可以使其更具可读性。
-(BOOL) hasPriceChanged{
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    formatter.numberStyle = NSNumberFormatterDecimalStyle;
    formatter.maximumFractionDigits = 4;
    NSString *p = [formatter stringFromNumber:self.price];
    NSString *op = [formatter stringFromNumber:self.originalPrice];
    return ![p isEqualToString:op];
}