次のC#ハッシュ関数(SOにもあります!)があります。これは、いくつかの異なるプラットフォームをカバーする一連のアプリで使用しています。
public static int GetStableHash(string s, int hashlength)
{
uint hash = 0;
var bytes = System.Text.Encoding.ASCII.GetBytes(s);
foreach (byte b in bytes)
{
hash += b;
hash += (hash << 10);
hash ^= (hash >> 6);
}
// final avalanche
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return (int)(hash % hashlength);
}
私はそれをJavascriptに移植しようとしています。そこでは、別のアプリが一致するハッシュを生成します。唯一の問題は、JSにuintタイプがなく、ビット単位の計算を実行する前に、内部でintをfloatに変換しているように見えることです。これにより、この移植された関数で問題が発生しています。
function getStableHash(s, hashlength)
{
var hash = 0;
var bytes = stringToBytes(s); // this function just grabs a byte array for the given input string
for (var i = 0; i < bytes.length; i++)
{
hash += bytes[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
// final avalanche
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return Math.round(hash % hashlength);
}
上記のコードでは、シフトによって符号ビットが存在するために問題が発生し、結果のハッシュがC#バージョンの出力と一致しません。他のさまざまなSO投稿(たとえば、大きな整数を使用したビット演算を参照)から、これを解決するための最良の方法が何であるかは不明です。
C#およびC ++のハッシュメソッドを使用するコードはすでに本番環境にあるため、Javascriptの欠点に対応するためにハッシュメソッドを他の場所に変更することはできません。
JSの内部型変換を回避するにはどうすればよいですか?