[英]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
從本質上講,它歸結為兩件事:
可移植性:當你獲取float的二進制表示時,那么在某個平台上,具有相同值的float可能有多個二進制表示。 我不知道是否存在這樣一個存在問題的平台,但由於解密數字的復雜性,我不確定這是否真的會發生。
第二個問題是你提出的,可能是sizeof(float)
不等於sizeof(int)
。
我沒有發現任何人提到boost hash確實避免了更少的沖突。 雖然我認為將尾數與指數分開可能會有所幫助,但上述鏈接並不表明這是驅動設計決策。
不使用位模式的一個原因是必須將一些不同的位模式視為等於並因此具有相同的散列碼,即
為什么要散列浮點值? 出於同樣的原因,比較浮點值的相等性存在許多缺陷,散列它們可能會產生類似(負面)的后果。
但是考慮到你確實想要這樣做,我懷疑升壓算法很復雜,因為當你考慮非規范化數字時,不同的位模式可以表示相同的數字(並且應該具有相同的散列)。 在IEEE 754中,還存在正0
和負0
值,它們相等但具有不同的位模式。
如果在算法中不會出現這種情況,這可能不會出現在散列中,但是您仍然需要注意信號NaN值。
另外,散列+/-無窮大和/或NaN的含義是什么? 特別是NaN可以有很多表示,如果它們都導致相同的哈希? 無限似乎只有兩個表示,所以看起來它可以正常工作。
我想這是兩台具有不兼容的浮點格式的機器散列到相同的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.