2009-06-08 9 views
3

C#でSystem.Drawing.PointクラスのカスタムGetHashCodeを実装しています。 。私は新しいSHA256Managed()ComputeHash(currentHash)を使用して行いますことを確信しているこのテストに合格するには最速のハッシュコードジェネレータ.NET

var hashA = MyGetHashCode(new Point(1, 0)); 
var hashB = MyGetHashCode(new Point(0, 1)); 
var hashC = MyGetHashCode(new Point(0, 0)); 
var hashD = MyGetHashCode(new Point(1, 1)); 
Assert.AreNotEqual(hashA^hashB, hashC^hashD); 

:私の方法は、現在、次の要件を失敗しました。しかし、他に高速なハッシュアルゴリズムがありますか?私はSHA256がセキュリティに関するすべてであることを知っています。私はそれを必要としません。

+1

あなたのハッシュ関数は、その試験に合格しなければならないという考えを思い付いたきっかけは? – mquander

+0

@私のカスタムPoint.GetHashCodeメソッドに依存している単純なGetHashCode実装に依存しています –

+0

@mquanderそれは、EqualsとGetHashCodeでコードを繰り返さないことと同等であることです。 –

答えて

6

単純なハッシュですか?どのようなものについて:

(17 * point.X) + (23 * point.Y); 

以上の明白なエントロピーのために:

int hash = -1047578147; 
hash = (hash * -1521134295) + point.X; 
hash = (hash * -1521134295) + point.Y; 

(C#の匿名型コードから番号)

+1

Marc、これは確実にAssertを実行しますが、(大きなXまたはYはオーバーフローします)...オーバーフローを許可した場合、良好なディストリビューションが得られません –

+1

ラップ(チェックされません)、分布はAFAIK 、fine ...これはC#コンパイラで使用されているアプローチです;-p –

+0

あなたはどこにいますか定数? BTWホルヘが正しいです。 –

1

私はこれがあなたの質問に答えるつもりはないですけど、他の読者のために、フレームワークの組み込みメソッドのデフォルト動作を変更していると言わなければなりません。ドキュメントごとの通り:
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

GetHashCodeメソッドのデフォルトの実装は 異なるオブジェクトためない 保証独自の戻り値を行います。さらに、 .NET Frameworkは、 のGetHashCodeメソッドの既定の実装を保証せず、 の値が同じ の.NET フレームワークで同じになります。したがって、このメソッドのデフォルトの の実装では、は、ハッシュ目的で という識別子をユニークなオブジェクトとして使用しないと、 を使用する必要がありません。

+0

blockquote、コードブロックではない(インデントの代わりに ">"をつけて引用符を付ける)?それは読みやすくするでしょう。 –

+0

この場合は問題ありません。つまり、異なるオブジェクトが同じハッシュを返すことができるため、デフォルトのGetHashcodeを一意の値として使用しないでください。 Jaderが(実際に)独自の価値(sha256などを使用して)を実装すると、何も破壊されません。それはちょうど遅くなるでしょう... – tanascius

+0

彼が実際にポイントの大きなハッシュテーブルを持っている場合、それはかなり遅いです - それはかなりばかげている十分に遅い。 – mquander

3
  • なぜあなたはこれをやっていますか?確かにSystem.Drawing.Pointには、既に細かいハッシュ関数がありますか?

  • あなたはテストが厳しい要件を表しているわけではないことを理解していますか?ハッシュコードは一意である必要はありません。

    本当に問題の座標のハッシュが必要な場合は、複数の整数をハッシュすることについてthis pageから始めたいと思うかもしれません。

+0

"細かいハッシュ関数" - x^y ...これは素晴らしいことではありません。対角線上の何かがゼロであり、対称的なもの、すなわち(5,7)と(7,5) - が等しいことを意味します。 –

+0

それは素晴らしいことではありませんが、病理学的な点分布がない限り、問題ありません。 SHAハッシュの使用を検討している場合、OPが具体的なパフォーマンス要件を満たしていないと感じているので、より良いものが必要なのかどうかは疑問です。 – mquander

+0

私は質問のコメントの最初の質問に答えました。 –

1

シンプルなエルフのハッシュ実装「

function ElfHash(id : string; tableSize : integer) : integer; 
var 
    i : integer; 
    h,x : longint; 
begin 
    h := 0; 
    // Obtener el valor numérico 
    for i := 1 to Length(id) do 
    begin 
    h := (h shl 4) + Ord(id[i]); 

    x := h and $F0000000; 
    if x <;>; 0 then 
     h = h xor (x shr 24) xor x; 
    end; 
    // Ajustar al tamaño de la tabla 
    result := h mod tableSize; 
end; 
+0

私はデルファイを知っていると思っていましたが、私は何も考えていません<;>;手段 –

+0

:) stackoverflowのsanitizerコードとの対話...それはちょっと "<>" –

+0

シフトを左、シフト右、排他的またはマネージコードで行うことを求めている間、 "翻訳しやすい"と言う。 – Hogan

0

私はドン(これはDelphiでだ、翻訳することは容易でshoudl)あなたのアプリケーションが何であるかを知っていますが、Zobristのハッシングを探しているかもしれません。

http://en.wikipedia.org/wiki/Zobrist_hashing

非常に高速になりこれ、増分更新することができます。

0

ポイント値が0からNの間であることが事前に分かっている場合は、hashcode = X+Y*N;を使用できます。これは明らかに可能なハッシュです。それはまったくランダムではなく、醜い反復を持ち、一般的にはかなり愚かです。これは、Nが2の累乗であると仮定すると、2点のビットを連結することと等価です。そして、それは完璧な一様分布と衝突なしです。

私は過去に優れた効果を発揮するためにこの戦略を使用しましたが、実際の(しかし明らかな)制限があることを認めています。最大のものは、NはN^2(すなわち痛みを伴う衝突あなたのハッシュ値に適合しないことが十分に大きいときに何が起こるかであること。

+0

私の現在の実装はあなたの記述に合った((x << 16) | (x >> 16))^ y(C#で)です –