一意性と速度に最適なハッシュアルゴリズムはどれですか?


1388

一意性と速度に最適なハッシュアルゴリズムはどれですか?例(良い)にはハッシュ辞書が含まれます。

私はSHA-256などのようなものがあることを知っていますが、これらのアルゴリズムは安全であるように設計されています。これは通常、一意性の低いアルゴリズムよりも遅いことを意味します。衝突を避けるために、高速でありながらかなりユニークなハッシュアルゴリズムを設計したいと考えています。


9
セキュリティまたはその他の目的は何ですか?
11

19
@Orbling、ハッシュ辞書の実装用。したがって、衝突は最小限に抑える必要がありますが、セキュリティ上の目的はまったくありません。
アールズ

4
あなたは、少なくとも期待する必要があることに注意してくださいいくつかそうでない場合は、テーブルには、キーの比較的少数...扱うことができるように膨大なものにする必要があります、あなたのハッシュテーブル内の衝突を
ディーン・ハーディング

19
素晴らしい投稿!また、Murmurの2倍の速さのYann ColletのxxHash(作成者またはLZ4)を確認できますか?ホームページ:code.google.com/p/xxhashさらに詳しい情報:fastcompression.blogspot.fr/2012/04/...

24
@zvrbaアルゴリズムに依存します。bcryptは低速になるように設計されています。
イズカタ

回答:


2461

速度と衝突回数を測定して、いくつかの異なるアルゴリズムをテストしました。

3つの異なるキーセットを使用しました。

各コーパスについて、衝突の数とハッシュに費やされた平均時間を記録しました。

私はテストしました:

結果

各結果には、平均ハッシュ時間と衝突数が含まれます

Hash           Lowercase      Random UUID  Numbers
=============  =============  ===========  ==============
Murmur            145 ns      259 ns          92 ns
                    6 collis    5 collis       0 collis
FNV-1a            152 ns      504 ns          86 ns
                    4 collis    4 collis       0 collis
FNV-1             184 ns      730 ns          92 ns
                    1 collis    5 collis       0 collis▪
DBJ2a             158 ns      443 ns          91 ns
                    5 collis    6 collis       0 collis▪▪▪
DJB2              156 ns      437 ns          93 ns
                    7 collis    6 collis       0 collis▪▪▪
SDBM              148 ns      484 ns          90 ns
                    4 collis    6 collis       0 collis**
SuperFastHash     164 ns      344 ns         118 ns
                   85 collis    4 collis   18742 collis
CRC32             250 ns      946 ns         130 ns
                    2 collis    0 collis       0 collis
LoseLose          338 ns        -             -
               215178 collis

衝突は実際に起こりますか?

はい。ハッシュの衝突が実際に起こるかどうかを確認するためにテストプログラムを書き始めました。彼らは実際に起こります:

FNV-1の衝突

  • creamwove 衝突する quists

FNV-1aの衝突

  • costarring 衝突する liquid
  • declinate 衝突する macallums
  • altarage 衝突する zinke
  • altarages 衝突する zinkes

Murmur2の衝突

  • cataract 衝突する periti
  • roquette 衝突する skivie
  • shawl 衝突する stormbound
  • dowlases 衝突する tramontane
  • cricketings 衝突する twanger
  • longans 衝突する whigs

DJB2コリジョン

  • hetairas 衝突する mentioner
  • heliotropes 衝突する neurospora
  • depravement 衝突する serafins
  • stylist 衝突する subgenera
  • joyful 衝突する synaphea
  • redescribed 衝突する urites
  • dram 衝突する vivency

DJB2aの衝突

  • haggadot 衝突する loathsomenesses
  • adorablenesses 衝突する rentability
  • playwright 衝突する snush
  • playwrighting 衝突する snushing
  • treponematoses 衝突する waterbeds

CRC32コリジョン

  • codding 衝突する gnu
  • exhibiters 衝突する schlager

SuperFastHashの衝突

  • dahabiah 衝突する drapability
  • encharm 衝突する enclave
  • grahams 衝突する gramary
  • ... 79回の衝突...
  • night 衝突する vigil
  • nights 衝突する vigils
  • finks 衝突する vinic

ランダムネス化

もう1つの主観的な尺度は、ハッシュがどの程度ランダムに分散されているかです。結果のHashTablesをマッピングすると、データが均等に分散されることがわかります。テーブルを線形にマッピングすると、すべてのハッシュ関数が良好な分布を示します。

ここに画像の説明を入力してください

または、ヒルベルトマップとして(XKCDは常に関連します):

ここに画像の説明を入力してください

番号文字列(ハッシュする場合を除き"1""2"、...、 "216553")(例えば、郵便番号パターンは、ハッシュアルゴリズムのほとんどに出現し始めます)、:

SDBM

ここに画像の説明を入力してください

DJB2a

ここに画像の説明を入力してください

FNV-1

ここに画像の説明を入力してください

FNV-1aを除くすべては、まだ私にはかなりランダムに見えます:

ここに画像の説明を入力してください

実際、Murmur2次のものよりもランダム性がさらに優れているようNumbersですFNV-1a

ここに画像の説明を入力してください

私が見たときFNV-1a「番号」マップ、私は考えて、私は微妙な縦パターンを参照してください。つぶやきでは、パターンはまったく見られません。どう思いますか?


*表の余分は、ランダム性がどれほど悪いかを示しています。FNV-1a最高であること、そしてDJB2x最悪のこと:

      Murmur2: .
       FNV-1a: .
        FNV-1: ▪
         DJB2: ▪▪
        DJB2a: ▪▪
         SDBM: ▪▪▪
SuperFastHash: .
          CRC: ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪
     Loselose: ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪
                                        ▪
                                 ▪▪▪▪▪▪▪▪▪▪▪▪▪
                        ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪
          ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪

私はもともとこのプログラムを書いて、衝突について心配する必要があるかどうかを判断しました。

そして、ハッシュ関数が十分にランダムであることを確認することになりました。

FNV-1aアルゴリズム

FNV1ハッシュには、32、64、128、256、512、および1024ビットのハッシュを返すバリアントがあります。

FNV-1aのアルゴリズムは次のとおりです。

hash = FNV_offset_basis
for each octetOfData to be hashed
    hash = hash xor octetOfData
    hash = hash * FNV_prime
return hash

定数FNV_offset_basisFNV_prime戻りハッシュサイズに依存する場所:

Hash Size  
===========
32-bit
    prime: 2^24 + 2^8 + 0x93 = 16777619
    offset: 2166136261
64-bit
    prime: 2^40 + 2^8 + 0xb3 = 1099511628211
    offset: 14695981039346656037
128-bit
    prime: 2^88 + 2^8 + 0x3b = 309485009821345068724781371
    offset: 144066263297769815596495629667062367629
256-bit
    prime: 2^168 + 2^8 + 0x63 = 374144419156711147060143317175368453031918731002211
    offset: 100029257958052580907070968620625704837092796014241193945225284501741471925557
512-bit
    prime: 2^344 + 2^8 + 0x57 = 35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759
    offset: 9659303129496669498009435400716310466090418745672637896108374329434462657994582932197716438449813051892206539805784495328239340083876191928701583869517785
1024-bit
    prime: 2^680 + 2^8 + 0x8d = 5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573
    offset: 1419779506494762106872207064140321832088062279544193396087847491461758272325229673230371772250864096521202355549365628174669108571814760471015076148029755969804077320157692458563003215304957150157403644460363550505412711285966361610267868082893823963790439336411086884584107735010676915

詳細については、メインのFNVページを参照してください。

私のすべての結果は、32ビット版のものです。

FNV-1はFNV-1aよりも優れていますか?

いいえ。FNV-1aの方が優れています。英語の単語コーパスを使用すると、FNV-1aとの衝突がさらに多くなりました。

Hash    Word Collisions
======  ===============
FNV-1   1
FNV-1a  4

小文字と大文字を比較します。

Hash    lowercase word Collisions  UPPERCASE word collisions
======  =========================  =========================
FNV-1   1                          9
FNV-1a  4                          11

この場合、FNV-1aはFN-1よりも「400%」悪くなく、20%だけ悪いです。

より重要なことは、衝突に関しては2つのクラスのアルゴリズムがあることだと思います。

  • まれな衝突:FNV-1、FNV-1a、DJB2、DJB2a、SDBM
  • 一般的な衝突:SuperFastHash、Loselose

そして、ハッシュがどの程度均等に分散されているかがあります。

  • 顕著な分布: Murmur2、FNV-1a、SuperFastHas
  • 優れた分布: FNV-1
  • 良好な分布: SDBM、DJB2、DJB2a
  • 恐ろしい分布:ロセロース

更新

つぶやき?もちろん


更新

@whatshisnameは、CRC32がどのように機能するか疑問に思い、表に数字を追加しました。

CRC32はかなり良いです。衝突はほとんどありませんが、速度が遅く、1kルックアップテーブルのオーバーヘッドです。

CRC分布に関するすべての誤った情報を切り取る-悪い


今日まで、事実上のハッシュテーブルハッシュアルゴリズムとしてFNV-1aを使用していました。しかし、今私はMurmur2に切り替えています:

  • もっと早く
  • 入力のすべてのクラスのランダム性の改善

そして、本当にSuperFastHash見つけアルゴリズムに何か問題があることを本当に願っています。そんなに人気があるのは残念だ。

更新:GoogleのMurmurHash3ホームページから:

(1)-SuperFastHashの衝突特性は非常に低く、他の場所で文書化されています。

だから、私だけではないようです。

更新:なぜMurmur他のものよりも高速であることに気付きました。MurmurHash2は、一度に4バイトで動作します。ほとんどのアルゴリズムはバイトごとです:

for each octet in Key
   AddTheOctetToTheHash

これは、キーが長くなるとMurmurが光るチャンスを得ることを意味します。


更新

GUIDは、ランダムではなく一意になるように設計されています

Raymond Chenによるタイムリーな投稿では、「ランダムな」 GUIDがランダム性のために使用されることを意図していないという事実を繰り返し述べています。それら、またはそれらのサブセットは、ハッシュキーとして不適切です。

バージョン4のGUIDアルゴリズムであっても、アルゴリズムは乱数ジェネレーターの品質を指定しないため、予測不能であることは保証されていません。GUIDのWikipediaの記事には、乱数ジェネレーターの状態に関する知識に基づいて、ジェネレーターが暗号的に強力ではないため、将来および以前のGUIDを予測できることを示唆する主要な研究が含まれています

Randomessは衝突回避と同じではありません。これが、「ランダム」なGUIDのサブセットを取得して、独自の「ハッシュ」アルゴリズムを発明しようとするのが間違いになる理由です。

int HashKeyFromGuid(Guid type4uuid)
{
   //A "4" is put somewhere in the GUID.
   //I can't remember exactly where, but it doesn't matter for
   //the illustrative purposes of this pseudocode
   int guidVersion = ((type4uuid.D3 & 0x0f00) >> 8);
   Assert(guidVersion == 4);

   return (int)GetFirstFourBytesOfGuid(type4uuid);
}

:繰り返しますが、「ランダムなGUID」を引用符で囲みます。これは、GUIDの「ランダムな」バリアントであるためです。より正確な説明は次のようになりますType 4 UUID。しかし、タイプ4またはタイプ1、3、5が何であるかは誰にもわかりません。したがって、それらを「ランダムな」GUIDと呼ぶ方が簡単です。

すべての英単語ミラー


41
SHAがここでのハッシュアルゴリズムの良い候補だからではなく、SHAがどのように比較されるかを見るのは本当に面白いでしょう。
マイケル

8
Yann Colletによる「xxHash」という名前の新しいハッシュが最近ラウンドを行っていました。私はいつも新しいハッシュを疑っています。あなたの比較でそれを見るのは面白いでしょう(あなたが聞いたことがあるランダムなハッシュを追加することを提案している人々にうんざりしていない場合...)
th_in_gs

7
確かに。xxHashプロジェクトページで発表されたパフォーマンスの数値は印象的で、多すぎるかもしれません。まあ、少なくとも、それはオープンソースプロジェクトです:code.google.com/p/xxhash
ATTracker

9
こんにちはIan、DelphiでのSuperFastHashの実装は正しいです。実装時に、CとDelphiでテストセットを作成して、実装と参照実装の結果を比較しました。違いはありません。だからあなたが見るのはハッシュの実際の悪さです...(だから私はMurmurHashの実装も公開しました:landman-code.blogspot.nl/2009/02/…
デイビーランドマン

19
ポスターは、これが単なる素晴らしい答えではないことを認識していますか?これは、このテーマに関する世界の事実上の参考資料です?ハッシュを処理する必要があるときはいつでも、それは私の問題を非常に速く、権威をもって解決するので、私は他に何も必要としません。
MaiaVictor

59

変わらない辞書からハッシュマップを作成する場合は、完全なハッシュhttps://en.wikipedia.org/wiki/Perfect_hash_functionを検討することをお勧めします -ハッシュ関数とハッシュテーブルの構築中に、特定のデータセットについては、衝突はありません。


2
ここで(最小限)パーフェクトハッシュの詳細ですburtleburtle.net/bob/hash/perfect.html、それはほとんどの現在のプロセッサなどを使用していないものの、パフォーマンスデータを含む
エリーKesselman

4
当たり前のことですが、衝突が発生しないことを保証するために、アルゴリズムが活用できる値に制約がない限り、キーは値と同じサイズでなければなりません。
devios1

1
@ devios1あなたの声明は無意味です。まず、ハッシュテーブルの値は、完全かどうかに関係なく、キーに依存しません。第二に、完全なハッシュテーブルは値の線形配列であり、すべてのインデックスが一意になるように作成された関数の結果によってインデックスが付けられます。
ジムBalter

1
@MarcusJパーフェクトハッシュは通常、100個未満のキーで使用されますが、cmph.sourceforge.netをご覧 ください。
ジムBalter

1
@DavidCaryあなたの主張をサポートするリンクはありません。おそらくO(1)を「衝突なし」と混同しているかもしれませんが、それらはまったく同じものではありません。もちろん、完全なハッシュは衝突がないことを保証しますが、すべてのキーが事前に知られていること、およびそれらのキーが比較的少ないことが必要です。(ただし、上記CMPHするためのリンクを参照してください。)
ジム・Balter

34

ハッシュ関数のリストを次に示しますが、短いバージョンは次のとおりです。

あなたが良いハッシュ関数を持ちたいだけで、待つことができない場合、djb2私が知っている最高の文字列ハッシュ関数の1つです。さまざまなキーセットとテーブルサイズで優れた分散と速度を実現

unsigned long
hash(unsigned char *str)
{
    unsigned long hash = 5381;
    int c;

    while (c = *str++)
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

    return hash;
}

6
実際、djb2はほとんどの単純なハッシュ関数と同様にゼロに敏感なので、そのようなハッシュを簡単に破ることができます。偏りが多く、衝突が多く、分布が悪いため、ほとんどのsmhasher品質テストで破損し ます。github.com/ rurban / smhasher / blob / master / doc / bernsteinを参照してください。パブリックアクセス。
rurban

2
DJBはパフォーマンスと配信の観点からはかなり悪いです。今日は使いません。
コンラッドマイヤー

@ConradMeyerきっと、この質問のようにDJBを3倍高速化できれば、おそらくほとんどの使用可能なアルゴリズムに勝るでしょう。配布に関して、私は同意します。2文字の文字列であっても、衝突を引き起こすハッシュはあまりよくありません。
-maaartinus

28

GoogleのCityHashは、探しているアルゴリズムです。暗号化には適していませんが、一意のハッシュの生成には適しています。

詳細についてはブログをご覧ください。コードはこちらから入手できます

CityHashはC ++で書かれています。また、プレーンなCポートもあります

32ビットのサポートについて:

すべてのCityHash関数は、64ビットプロセッサ用に調整されています。ただし、これらは32ビットコードで実行されます(SSE4.2を使用する新しいものを除く)。しかし、それらはあまり速くありません。32ビットコードでMurmurなどを使用することもできます。


11
CityHashは「City Sushi?」と同様に発音されますか?
エリック

2
SipHashもご覧ください。MurmurHash/ CityHash / etcを置き換えるものです。:131002.net/siphash
Törökエドウィン

3
CitHashの後継であるFarmHashも参照してください。code.google.com/p/farmhash
stevendaniels

7
xxHashは、CityHashより5倍高速であると主張しています。
クレイブリッジズ

plain C portリンクが壊れています
-makerj

20

ファイルをハッシュするときのさまざまなハッシュアルゴリズムの短い速度の比較をプロットしました。

すべてのファイルはtmpfsに保存されているため、個々のプロットは読み取り方法がわずかに異なるだけで、ここでは無視できます。したがって、疑問がある場合は、ベンチマークはIOにバインドされていません。

アルゴリズムは次のとおりSpookyHash, CityHash, Murmur3, MD5, SHA{1,256,512}です。

結論:

  • Murmur3、Cityhash、Spookyのような非暗号化ハッシュ関数は非常に近いものです。CRC私のCPUにはないSSE 4.2s 命令を使用したCPUでは、Cityhashの方が高速になる可能性があることに注意してください。SpookyHashは私の場合、CityHashの前は常にほんの少しでした。
  • 暗号化ハッシュ関数を使用する場合、MD5は良いトレードオフのようですが、SHA256 はMD5とSHA1の衝突の脆弱性に対してより安全である可能性があります。
  • すべてのアルゴリズムの複雑さは線形です-ブロックごとに機能するため、これは本当に驚くことではありません。(読み取り方法が違いをもたらすかどうかを確認したかったので、右端の値を比較するだけです)。
  • SHA256はSHA512よりも低速でした。
  • ハッシュ関数のランダム性を調査しませんでした。しかし、ここに欠けているハッシュ関数の良い比較であるイアン・Boydsの答えが。これは、CityHashがいくつかの問題を抱えていることを指摘しています。

プロットに使用されるソース:


1
線形スケールグラフは、プロットする量を示すy軸ラベルを切り取ります。対数スケールと同じ「秒単位の時間」になると思います。修正する価値があります。
クレイグマックイーン

18

SHAアルゴリズム(SHA-256を含む)は、高速になるように設計されています。

実際、その速度が問題になる場合があります。特に、パスワードから派生したトークンを保存する一般的な手法は、標準の高速ハッシュアルゴリズムを10,000回実行することです(...パスワードのハッシュのハッシュのハッシュのハッシュを保存する)。

#!/usr/bin/env ruby
require 'securerandom'
require 'digest'
require 'benchmark'

def run_random_digest(digest, count)
  v = SecureRandom.random_bytes(digest.block_length)
  count.times { v = digest.digest(v) }
  v
end

Benchmark.bmbm do |x|
  x.report { run_random_digest(Digest::SHA256.new, 1_000_000) }
end

出力:

Rehearsal ------------------------------------
   1.480000   0.000000   1.480000 (  1.391229)
--------------------------- total: 1.480000sec

       user     system      total        real
   1.400000   0.000000   1.400000 (  1.382016)

57
暗号化ハッシュアルゴリズムの場合は、比較的高速です。しかし、OPは単にハッシュテーブルに値を保存したいだけであり、暗号化ハッシュ関数がそのために本当に適切だとは思いません。
ディーンハーディング

6
質問は、暗号ハッシュ関数の主題を提起しました(接線上、現在では表示されています)。それは私が応答しているビットです。
イフェルドブルム

15
「特に、パスワードから派生したトークンを保存するための一般的な手法は、標準の高速ハッシュアルゴリズムを10,000回実行することです」という考えをやめるためです。これらのシナリオ用に設計されたアルゴリズムがありますbcrypt。適切なツールを使用してください。
TC1

3
暗号化ハッシュはスループットが高くなるように設計されていますが、多くの場合、セットアップ、分解、.rodataおよび/または状態のコストが高いことを意味します。ハッシュテーブル用のアルゴリズムが必要な場合、通常は非常に短いキーと多くのキーがありますが、暗号化の追加の保証は必要ありません。調整済みのJenkinsを1つずつ使用します。
ミラビロス

1
@ChrisMorgan:暗号的に安全なハッシュを使用するのではなく、ハッシュランダム化を使用してHashTable DoSをはるかに効率的に解決できるため、プログラムのすべての実行またはすべてのハッシュテーブルでさえ、データが毎回同じバケットにグループ化されることはありません。
嘘ライアン

14

私はSHA-256などのようなものがあることを知っていますが、これらのアルゴリズムは安全になるように設計されています。これは通常、一意性の低いアルゴリズムよりも遅いことを意味します。

暗号化ハッシュ関数がより一意であるという仮定は間違っており、実際には実際にはしばしば後方にあることが示されます。実際には:

  1. 暗号ハッシュ関数は理想的にランダム区別できないはずです;
  2. しかし、非暗号化ハッシュ関数を使用する場合は、可能性の高い入力と良好相互作用することが望ましいです。

つまり、非暗号化ハッシュ関数は、「適切な」データセット(設計されたデータセット)の暗号化ハッシュ関数よりも衝突少ない可能性があります。

Ian Boydの回答のデータと少しの数学:誕生日問題で実際にこれを実証できますnセットから整数をランダムに選択した場合の衝突ペアの予想数の式は次のとおりです[1, d](ウィキペディアから取得)。

n - d + d * ((d - 1) / d)^n

プラグnイン= 216,553およびd= 2 ^ 32では、約5.5の予想される衝突が発生します。Ianのテストはほとんどその周辺の結果を示しますが、1つの劇的な例外を除いて、ほとんどの関数は連続番号テストで衝突ゼロにしました。216,553個の32ビット数をランダムに選択し、衝突がゼロになる確率は約0.43%です。そして、それは1つの関数だけです。ここでは、衝突がゼロの5つの異なるハッシュ関数ファミリがあります。

したがって、ここで見ているのは、Ianがテストしたハッシュが連続番号データセットと良好に相互作用していることです。つまり、理想的な暗号化ハッシュ関数よりも広く、最小限の異なる入力を分散しています。(サイドノート:これは数字のデータセットで彼に「ランダムに見える」イアンのグラフィカルな評価というFNV-1aおよびMurmurHash2という意味では、彼自身のデータから反論することができ、そのサイズのデータセット上のゼロの衝突のために。両方のハッシュ関数、驚くほど非ランダムです!)

これは、ハッシュ関数の多くの使用にとって望ましい動作であるため、驚くことではありません。たとえば、ハッシュテーブルキーはよく似ています。Ianの回答は、MSNがかつて郵便番号ハッシュテーブルで抱えていた問題に言及しています。これは、可能性のある入力での衝突回避がランダムのような動作に勝る用途です。

ここでのもう1つの有益な比較は、CRCと暗号化ハッシュ関数の設計目標の対照です。

  • CRCは、ノイズの多い通信チャネルに起因するエラーをキャッチするように設計されています。これは、少数のビットフリップである可能性が高いです。
  • 暗号ハッシュは、悪意のある攻撃者によって行われた変更をキャッチするように設計されています。

したがって、CRCの場合、最小限の異なる入力で、ランダムよりもコリジョンが少ない方が良いです。暗号ハッシュでは、これは不可です!


10

SipHashを使用します。それは持っている多くの望ましい特性を:

  • 速い。 最適化された実装には、1バイトあたり約1サイクルかかります。

  • 安全。 SipHashは強力なPRF(疑似ランダム関数)です。これは、ランダム関数と区別できないことを意味します(128ビットの秘密鍵を知らない限り)。したがって:

    • 衝突によりハッシュテーブルプローブが線形時間になることを心配する必要はありません。SipHash を使用すると、入力に関係なく、平均的なケースのパフォーマンスが得られることがわかります。

    • ハッシュベースのサービス拒否攻撃に対する耐性。

    • SipHash(特に128ビット出力のバージョン)をMAC(メッセージ認証コード)として使用できます。メッセージとSipHashタグを受信し、タグが秘密キーを使用してSipHashを実行した場合と同じ場合、ハッシュを作成した人も秘密キーを所有しており、メッセージも以降、ハッシュが変更されました。


1
セキュリティが必要でない限り、SipHashは過剰ではありませんか?128ビットキーが必要です。これは、単なるハッシュシードです。MurmurHash3には128ビットの出力があり、SipHashには64ビットの出力しかありません。明らかに、ダイジェストが大きいほど、衝突の可能性は低くなります。
-bryc

@bryc違いは、SipHashは悪意のある入力に対しても引き続き適切に動作することです。SipHashに基づいたハッシュテーブルは、潜在的に敵意のあるソースからのデータに使用でき、ハッシュ関数の詳細に非常に敏感な線形プローブなどのアルゴリズムを使用できます。
デミ

9

ハッシュするデータに依存します。一部のハッシュは、テキストなどの特定のデータでより適切に機能します。一部のハッシュアルゴリズムは、特定のデータに適した設計になっています。

Paul Hsiehはかつて高速ハッシュを作成しました。彼はソースコードと説明をリストしています。しかし、すでにbeatられていました。:)


6

Javaは、この単純な乗加算アルゴリズムを使用します。

Stringオブジェクトのハッシュコードは次のように計算されます

 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

int算術を使用します。ここs[i]で、は文字列のi番目の文字であり、文字列nの長さであり、^べき乗を示します。(空の文字列のハッシュ値はゼロです。)

おそらくもっと良いものがそこにありますが、これはかなり広範であり、速度と一意性の間の良いトレードオフのようです。


12
ここで使用したものとまったく同じものは使用しません。これとの衝突はまだ比較的簡単だからです。それはだ間違いなくひどいではないが、はるかに優れたものがそこにあります。また、Javaと互換性があるという重大な理由がない場合は、Javaを選択すべきではありません。
ヨアヒムザウアー

4
それでも何らかの理由でこのハッシュ方法を選択する場合は、少なくとも乗算器として92821などのより良い素数を使用できます。それは衝突を大幅に減らします。stackoverflow.com/a/2816747/21499
Hans-PeterStörr14年

1
代わりにFNV1aを使用することもできます。単純な乗算ベースのハッシュでもありますが、より大きな乗数を使用するため、ハッシュがよりよく分散されます。
bryc

4

まず、なぜ独自のハッシュを実装する必要があるのですか?ほとんどのタスクでは、利用可能な実装があると仮定して、標準ライブラリのデータ構造を使用して良好な結果を得る必要があります(独自の教育のためにこれを行っている場合を除きます)。

実際のハッシュアルゴリズムに関する限り、私の個人的なお気に入りはFNVです。1

Cの32ビットバージョンの実装例を次に示します。

unsigned long int FNV_hash(void* dataToHash, unsigned long int length)
{
  unsigned char* p = (unsigned char *) dataToHash;
  unsigned long int h = 2166136261UL;
  unsigned long int i;

  for(i = 0; i < length; i++)
    h = (h * 16777619) ^ p[i] ;

  return h;
}

2
FNV-1aバリアントは、ランダム性がわずかに優れています。*and の順序を交換し^ます。h = (h * 16777619) ^ p[i]==>h = (h ^ p[i]) * 16777619
Ian Boyd
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.