哈希浮点值
Hashing floating point values
最近,我很好奇浮点的哈希算法是如何工作的,所以我查看了boost::hash_value
的源代码。事实证明这相当复杂。实际实现在基数中的每个数字上循环,并累积一个哈希值。与整数散列函数相比,它涉及的内容要多得多。
我的问题是:为什么浮点散列算法要更复杂?为什么不把浮点值的二进制表示形式当作整数进行散列呢?
类似:
std::size_t hash_value(float f)
{
return hash_value(*(reinterpret_cast<int*>(&f)));
}
我意识到,在所有系统上,float
并不能保证与int
大小相同,但这类事情可以用一些模板元程序来处理,从而推导出与float
大小相同的积分类型。那么,引入一个完全不同的哈希函数,专门对浮点类型进行操作,有什么好处呢?
看看https://svn.boost.org/trac/boost/ticket/4038
从本质上讲,它可以归结为两件事:
-
可移植性:当你采用浮点的二进制表示时,在某些平台上,具有相同值的浮点可能有多个二进制表示。我不知道是否真的有这样一个平台存在这样的问题,但由于非正规数字的复杂性,我不确定这是否真的会发生。
-
第二个问题是你提出的,可能是
sizeof(float)
不等于sizeof(int)
。
我没有发现有人提到boost哈希确实避免了更少的冲突。尽管我认为将尾数与指数分开可能会有所帮助,但上述链接并不表明这是驱动设计的决定。
不使用比特模式的一个原因是,一些不同的比特模式必须被视为相等,因此具有相同的哈希码,即
- 正负零点
- 可能是非规范化的数字(我不认为IEEE 754会出现这种情况,但C允许其他浮点表示(
- 可能是NAN(至少在IEEE 754中存在许多。它实际上要求NAN模式被视为与自身不平等,这可以说意味着不能在哈希表中有意义地使用(
为什么要对浮点值进行散列?出于同样的原因,比较相等的浮点值有很多陷阱,对它们进行哈希处理可能会产生类似的(负面(后果。
然而,考虑到你真的想这样做,我怀疑boost算法很复杂,因为当你考虑非规范化的数字时,不同的比特模式可以表示相同的数字(并且可能应该有相同的散列(。在IEEE 754中,也存在比较相等但具有不同比特模式的正和负CCD_ 7值。
如果在你的算法中没有出现,这可能不会出现在哈希中,但你仍然需要注意NaN值的信号传递。
此外,散列+/-无穷大和/或NaN的含义是什么?具体来说,NaN可以有许多表示,它们是否都会产生相同的哈希?Infinity似乎只有两个表示,所以它似乎可以正常工作。
我想,两台浮点格式不兼容的机器会散列到相同的值。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 使用Qt C++计算类似Git的SHA1哈希
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 用C++将哈希表写入文件并从文件中恢复
- c++找不到具有相同哈希的无序集合元素
- 哈希文件递归并保存到矢量Cryptopp中
- 对 pair<pair<int,int>pair<int,int unordered_map进行哈希处理>>
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 如何为字符串生成唯一但一致的 N 位哈希(小于 64 位)?
- 使用对象的基类部分模板专用化对对象进行哈希处理::哈希
- boost::包含提升单元的元组的哈希值
- 使用 Key 对 C++ 中的哈希映射进行排序. 无法排序
- C++中的并发哈希表
- 哈希映射使用 nullptr c++ 初始化节点的动态数组
- 在具有开放寻址的哈希表中插入节点 [优化逻辑]
- 实现具有浮点键的类似哈希表的数据结构,其中公差内的值被合并在一起
- 从两个浮点向量生成哈希的最佳方法
- 哈希浮点值
- std::hash 是否保证"equal"浮点数的哈希值相等?