NSNumber 比较:返回不同的结果
我正在尝试进行一些数字比较,但得到了一些奇怪的结果。
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");
日志输出:
没有
是的
否
是的
这让我非常沮丧。我知道这可能是因为浮点数与双精度数之间的位数不同。在我看来,它将双精度截断为浮点数来进行比较。但如果我不知道数字是如何创建的,我如何获得正确的结果呢?有没有不同的方法来比较 NSNumber 的?
I'm trying to do some number comparisons and I'm getting some weird results.
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");
Log output:
NO
YES
NO
YES
This is extremely frustrating to me. I know this is probably because the difference between the number of bits in a float compared to a double. It seems to me it's truncating the double down to a float to do the compare. But if I don't know how the number is created, how do I get the correct results? Is there a different way to compare NSNumber's?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我尝试使用
isEqualToNumber:
但它返回 NO。它们不相同的原因是 1.004 无法用二进制精确表示。double
近似值比float
近似值的小数点后位数更多,因此两个数字不同。通常,在比较浮点数时,您会测试它们是否等于容差值fabs(a - b)
fabs(a - b) <公差
:结果:
I tried using
isEqualToNumber:
and it returned NO. The reason they aren't the same is because 1.004 can't be represented exactly in binary. Thedouble
approximation has more digits after the decimal point than thefloat
approximation so the two numbers are different. Normally, when comparing floating point numbers, you test to see if they are equal to within a tolerance valuefabs(a - b) < tolerance
:results:
请尝试使用
isEqualToNumber
: 方法来检查您的情况此 stackoverflow 问题也给出了详细的解答
please try the
isEqualToNumber
: method to check your conditionthis stackoverflow question also gives a detailed answer
Compare: 方法遵循类型转换的标准 C 规则。例如,如果将具有整数值的 NSNumber 对象与具有浮点值的 NSNumber 对象进行比较,则整数值将转换为浮点值进行比较。
另外,用 float 初始化 NSNumber,然后将其转换为 double 会丢失一些精度。
如果您知道可能混合使用浮点数和双精度数,一种解决方案是比较 NSNumber floatValues,就像您在问题中的代码片段的最后一行中所做的那样。
另外,您可以使用 objCType 方法获取 NSNumber 中数据的类型。
The compare: method follows the standard C rules for type conversion. For example, if you compare an NSNumber object that has an integer value with an NSNumber object that has a floating point value, the integer value is converted to a floating-point value for comparison.
Also, initializing an NSNumber with a float, then converting it to a double loses some precision.
If you know you may have a mix of float and doubles, one solution is to compare the NSNumber floatValues like you did in the last line of your code snippet in your question.
Also, you can get the type of the data in the NSNumber with the objCType method.
对我有用的另一个解决方案是将它们转换为 NSString 并进行字符串比较。这是因为我正在使用 4 位小数价格,这对我来说效果很好。
这解决了我比较带有 2 个尾随零的双精度型和没有尾随零的浮点数的问题。
我通常会警告不要进行这样的字符串比较,但由于我的规则总是固定的,在这种情况下对我来说没问题。
Another solution that worked for me was to convert them to NSStrings and do a string comparison. This was because I am working with 4 digit decimal prices and this worked well for me.
This got rid of the issue where I was comparing a double with 2 trailing zeros and a float with none.
I'd normally warn against string comparisons like this but as my rules were always fixed it was OK for me in this case.