0

我有以下 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 类型,并且似乎在执行按位数学之前在内部将整数转换为浮点数。这导致此移植功能出现问题:

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 的内部类型转换?

4

1 回答 1

2

尝试以下操作:

  1. 使用无符号右移>>>而不是有符号

  2. 用于在取模之前>>> 0将最终结果转换为无符号32 位 int:

    return (hash >>> 0) % hashlength;

于 2013-03-11T00:44:43.777 回答