Ios 值为0.5和1.0的NSNumber具有相同的哈希

Ios 值为0.5和1.0的NSNumber具有相同的哈希,ios,objective-c,nsnumber,Ios,Objective C,Nsnumber,请有人确认并解释为什么会发生这种情况: 在模拟器上(7.1,32位): 在设备上(7.1,32位): 我认为这可能是一个32位的问题,但当我在64位模拟器和设备上尝试同样的事情时,我得到了同样的问题。模拟器很好,设备有相同的散列 我试图向NSMutableOrderedSet添加唯一的对象,并注意到除了0.5和1.0的不同值之外,我的两个相同的对象没有同时添加,这就是原因。我试了两次浮球和双打,结果都一样 但是为什么呢?我认为迈克·阿什的这篇文章可能会给我们一些启示: 对于整型值的浮点,我们希望

请有人确认并解释为什么会发生这种情况:

在模拟器上(7.1,32位):

在设备上(7.1,32位):

我认为这可能是一个32位的问题,但当我在64位模拟器和设备上尝试同样的事情时,我得到了同样的问题。模拟器很好,设备有相同的散列

我试图向
NSMutableOrderedSet
添加唯一的对象,并注意到除了0.5和1.0的不同值之外,我的两个相同的对象没有同时添加,这就是原因。我试了两次浮球和双打,结果都一样

但是为什么呢?

我认为迈克·阿什的这篇文章可能会给我们一些启示:

对于整型值的浮点,我们希望做同样的事情。 因为我们的isEqual:认为整数值的DOUBLE等于INT 或相同值的UINT,我们必须返回与INT和 UINT当量。为了实现这一点,我们检查 值实际上是一个整数,如果是,则返回整数值:

    if(_value.d == floor(_value.d))
        return [self unsignedIntegerValue];
(关于
散列
,我不会引用整节内容,因此请阅读本文以获得充分披露)


但是,归根结底,使用
[NSNumber hash]
作为关联数组/哈希表中的键似乎不是一个好主意。然而,我无法解释为什么它在模拟器和设备下表现不同;这看起来有点麻烦…

不能保证不同输入的哈希值是不同的

在这种情况下,考虑有2个32散列值,并且有更大的唯一值<代码> NSSUTION>代码>,因此散列不能用于唯一性。 较短的散列通常用作快速初始比较,然后如果它与对象的完整比较匹配。这可能就是

NSNumber
isEqual
所做的

这就是为什么在
NSSet
中使用散列作为密钥是一个坏主意,并且出于Mike Ash引用@特洛伊木马的原因,
NSNumber
散列将不起作用


即使像SHA512这样的加密散列也不能保证对不同的输入产生不同的结果,但随着散列长度的增加,这种可能性很小。这就是为什么建议不要使用
MD5
,甚至
SHA2
也越来越多地被认为是做空

谢谢。。。但是,我如何编写对象的散列并记住
NSNumber
,使这两个对象是唯一的?另外,我不关心
isEqual:
,因为这实际上会返回正确的结果。不起作用的是散列。我还注意到,0.5到0.9之间的
NSNumber
s散列都返回相同的值。@jowie,但仅在设备上?在模拟器上,它看起来可以工作?是的-仅在设备上。不幸的是,这是解决问题的方法@乔维:是的,这很令人担忧。苹果公司建议使用字符串值作为键,这样你就可以尝试了:你理解
散列的概念吗?据我所知,它是一个无符号整数(我假设)提供了对具有特定值的对象的唯一引用。。。但是如果我遗漏了什么,请告诉我。是的,您遗漏了什么,
hash
不能保证唯一性。它就像一个邮政编码。很多人会共享相同的邮政编码,但当你在寻找某人时,邮政编码仍然是一个很大的帮助<如果你没有一个好的
isEqual
,那么代码>散列就没有意义了。维基百科:是的,我现在意识到了。我只是很惊讶NSNumber的散列只返回一个基于其unsignedInteger的值。我也不希望设备上的行为与模拟器有所不同。
NSNumber *a = [NSNumber numberWithFloat:0.5]; // hash = 2654435761
NSNumber *b = [NSNumber numberWithFloat:1.0]; // hash = 2654435761 - SAME!
NSNumber *c = [NSNumber numberWithFloat:2.0]; // hash = 5308871522
    if(_value.d == floor(_value.d))
        return [self unsignedIntegerValue];