在具有良好分布的两个整数之间散列字符串(统一散列)

时间:2013-06-13 09:12:21

标签: javascript algorithm hash

我正在尝试在0和非常低的n之间散列一些字符串,以便为每个用户提供一种颜色。

这是我的(工作)代码:

 function nameToColor(name) {
            var colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple'];
            var hash = hashStr(name);
            var index = hash % colors.length;
            return colors[index];
        }

        //djb2 hash
        function hashStr(str) {
            var hash = 5381;
            for (var i = 0; i < str.length; i++) {
                var charCode = str.charCodeAt(i);
                hash = ((hash << 5) + hash) + charCode; /* hash * 33 + c */
            }
            return hash;    
        }

不幸的是,低数字被大量过多。

问题:

如何编写一个确定性的javascript函数,它将任何字符串作为参数并返回一个好的(尽可能统一)分布,数字介于0和n之间?

2 个答案:

答案 0 :(得分:7)

Hogan在javascript中给了几个哈希实现评论link。事实证明,最简单的是最合适的:

function nameToColor(name) {
                var colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple'];
                var hash = hashStr(name);
                var index = hash % colors.length;
                return colors[index];
        }

        //very simple hash
        function hashStr(str) {
            var hash = 0;
            for (var i = 0; i < str.length; i++) {
                var charCode = str.charCodeAt(i);
                hash += charCode;
            }
            return hash;
        }

我认为它运作良好,因为它只使用与模运算符交换的加法(无移位或乘法),因此保持了初始分布质量。

我还在维基百科上找到了this,但没有必要使用它:

  

在许多应用程序中,散列值的范围对于程序的每次运行可能是不同的,或者可能沿着相同的运行而改变(例如,当需要扩展散列表时)。在这些情况下,需要一个哈希函数,它接受两个参数 - 输入数据z和允许哈希值的数量n。

     

一个常见的解决方案是用非常计算一个固定的哈希函数   大范围(例如,0到232 - 1),将结果除以n,并使用   师的剩余部分。如果n本身是2的幂,则可以通过以下方式完成   位屏蔽和位移。使用此方法时,哈希   必须选择函数以使结果相当均匀   在0和n - 1之间的分布,对于可能出现的任何n值   应用程序。根据功能,其余部分可能是   仅对n的某些值均匀,例如奇数或素数。

     

我们可以允许表格大小n不是2的幂,但仍然不是   必须执行任何剩余或除法操作,因为这些   计算有时是昂贵的。例如,让n显着   少于2b。考虑一个伪随机数发生器(PRNG)   函数P(key)在区间[0,2b-1]上是均匀的。哈希   区间[0,n-1]上的函数均匀是n P(密钥)/ 2b。我们可以   通过(可能更快的)右位移来代替除法:nP(键)&gt;&gt;湾

答案 1 :(得分:1)

Brian White的以下哈希函数非常通用,使用任何类型的输入(包括字符串),附带简单示例,并为Javascript node.js编写。

https://npmjs.org/package/xxhash

希望这有帮助