有人可以确认并解释为什么会发生这种情况:
在模拟器(7.1,32位)上:
NSNumber *a = [NSNumber numberWithFloat:0.5]; // hash = 506952114
NSNumber *b = [NSNumber numberWithFloat:1.0]; // hash = 2654435761
NSNumber *c = [NSNumber numberWithFloat:2.0]; // hash = 1013904226
在设备上(7.1,32位):
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
我认为这可能是一个32位的问题,但是当我在64位模拟器和设备上尝试同样的事情时,我得到了相同的问题。模拟器很好,设备有相同的哈希值。
我试图向NSMutableOrderedSet
添加唯一对象,并注意到除了0.5和1.0的不同值之外,我的两个相同的对象都没有被添加,这就是原因。我尝试了浮动和双打同样的结果。
但为什么?
答案 0 :(得分:2)
我认为来自Mike Ash的excellent article可能会提供一些见解:
对于整数值的浮点数,我们想要做同样的事情。 因为我们的isEqual:认为整数值DOUBLE等于INT 或UINT具有相同的值,我们必须返回与INT相同的哈希值 UINT等价。为此,我们检查是否有DOUBLE value实际上是一个整数,如果是这样,则返回整数值:
if(_value.d == floor(_value.d)) return [self unsignedIntegerValue];
(我不会引用关于hash
的整个部分,所以请阅读该文章以获得完整的披露。)
但是,底线,看起来使用[NSNumber hash]
作为关联数组/哈希表中的键是一个坏主意。但是我无法解释为什么它在模拟器和设备下表现不同;这看起来有点令人不安......
答案 1 :(得分:2)
无法保证不同输入的哈希值不同。
在这种情况下,请考虑有2 ^ 32个哈希值,并且有更多唯一NSSNumbers
的大小,因此哈希不能用于唯一性。
相当短的哈希通常用作快速初始比较,然后如果它与对象的完全比较匹配。这可能是NSNumber
isEqual
所做的。
这就是为什么在NSSet
中使用哈希作为键是一个坏主意,并且由于@ Ashjanfoe从Mike Ash引用的原因NSNumber
哈希将无效。
即使是像SHA512这样的加密哈希也不能保证为不同的输入产生不同的结果,但随着哈希长度的增加,机会很小。这就是为什么MD5
建议反对,甚至SHA2
越来越被认为是短暂的原因。