我正在尝试进行一些数字比较,而且我得到了一些奇怪的结果。
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");
日志输出:
NO
YES
NO
是的
这对我来说非常令人沮丧。我知道这可能是因为浮点数与双精度数之间的差异。在我看来,它正在将双倍缩减到浮点数来进行比较。但如果我不知道如何创建数字,我该如何得到正确的结果呢?是否有不同的方法来比较NSNumber?
答案 0 :(得分:7)
我尝试使用isEqualToNumber:
并返回NO。它们不相同的原因是因为1.004不能完全用二进制表示。 double
近似值在小数点后面的位数多于float
近似值,因此两个数字不同。通常,在比较浮点数时,您要测试它们是否等于公差值fabs(a - b) < tolerance
:
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");
结果:
2012-02-09 15:08:34.272 so9219935[3313:903] number 1: 1.003999948502
2012-02-09 15:08:34.274 so9219935[3313:903] number 2: 1.004000000000
2012-02-09 15:08:34.275 so9219935[3313:903] NO
2012-02-09 15:08:34.275 so9219935[3313:903] YES
答案 1 :(得分:2)
compare:方法遵循标准C规则进行类型转换。例如,如果将具有整数值的NSNumber对象与具有浮点值的NSNumber对象进行比较,则将整数值转换为浮点值以进行比较。
此外,使用float初始化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
如果你知道你可能有浮动和双打的混合,一种解决方案就是比较你问题代码片段最后一行中的NSNumber floatValues。
此外,您可以使用objCType方法获取NSNumber中的数据类型。
答案 2 :(得分:2)
请尝试使用isEqualToNumber
:方法检查您的病情
([number1 isEqualToNumber:number2]) ? NSLog(@"YES") : NSLog(@"NO");
this stackoverflow question也提供了详细的答案
答案 3 :(得分:0)
另一个对我有用的解决方案是将它们转换为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];
}
这摆脱了我在比较带有两个尾随零的double和没有浮点的浮点的问题。
我通常会警告不要进行这样的字符串比较,但是由于我的规则总是固定的,因此在这种情况下对我来说是可以的。