![](/img/trans.png)
[英]Why std::array<int, 10> x is not zero-initialized but std::array<int, 10> x = std::array<int, 10>() seems to be?
[英]Why std::hash<int> seems to be identity function
#include <iostream>
int main() {
std::hash<int> hash_f;
std::cout << hash_f(0) << std::endl;
std::cout << hash_f(1) << std::endl;
std::cout << hash_f(2) << std::endl;
std::cout << hash_f(3) << std::endl;
}
我用“g ++ main.cpp -std = c ++ 11”編譯,結果是:
0
1
2
3
為什么會這樣? 我不使用任何庫,我沒有專門的散列函數。
附錄:我想為int的unordered_set的unordered_set定義散列,其中集合的散列是其組件散列的總和,但如果它只是標識它並不酷,因為{2,4}的散列是相同的{1,5}的哈希值。 避免這種情況的最簡單方法可能是使用std :: hash double函數。
它似乎是它的身份,它允許作為其獨特的..來自cpp參考
實際的散列函數是依賴於實現的,除了上面指定的那些之外,不需要滿足任何其他質量標准。 值得注意的是,一些實現使用簡單(標識)散列函數將整數映射到自身。 換句話說,這些散列函數被設計為與無序關聯容器一起使用,但不是作為加密散列。 ....
哈希函數int
→ int
似乎是完全合理的,並且不清楚為什么你會對此感到驚訝。 執行任何進一步的計算將毫無意義。 事實上,這是該術語的每個意義上的完美哈希 。
請記住, std::hash
應該(幾乎唯一地) 標識值,而不是加密它們。
只有當你想要散列大於散列本身的類型(例如, uint9999999_t
)時,才需要做一些工作來將值“壓縮”為散列的大小。
其他答案很好地涵蓋了身份功能背后的基本原理。 要解決您的附錄:
我想將unordered_set的哈希值定義為其組件哈希值的總和,但如果只是身份識別它並不酷,因為{2,4}的哈希值與{1,5}的哈希值相同。 避免這種情況的最簡單方法可能是使用std :: hash函數。
如您所見,使用+
運算符組合哈希並不是最好的主意。 為了更加健壯,您可以使用XOR( ^
)運算符,或者從所采用的方法中獲取靈感,例如通過boost::hash_combine
( 此SO帖子中的詳細信息 ):
seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
例如,對於兩個整數對(1,5 / 2,4)和一個0的seed
,這將是有效的
uint32_t seed = 0;
seed ^= 1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= 5 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
// 3449077526
uint32_t seed = 0;
seed ^= 2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= 4 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
// 3449077584
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.