炎炎设计
尽管在Jon Skeet的答案中概述的模板通常可以很好地作为哈希函数系列使用,但是常量的选择很重要,答案中指出的种子17和因数31对于普通用例来说根本无法正常工作。在大多数使用情况下,散列的值比都更接近于零int.MaxValue,并且共同进行散列的项目数不超过几十个。对于散列一个整数的元组{x, y},其中-1000 <= x <= 1000和-1000 <= y <= 1000,它有将近98.5%的深不可测的碰撞率。例如{1, 0} -> {0, 31},{1, 1} -> {0, 32}等等。如果我们扩大覆盖范围还包括n元组在那里3 <= n <= 25,但它确实不太可怕的约38%的碰撞率。但是我们可以做得更好。public static int CustomHash(int seed, int factor, params int[] vals){ int hash = seed; foreach (int i in vals) { hash = (hash * factor) + i; } return hash;}我写了一个蒙特卡洛采样搜索循环,用随机种子的各个随机n元组的各种种子和因子值测试了上述方法i。允许的范围为2 <= n <= 25(其中n为随机范围,但偏向范围的下限)和-1000 <= i <= 1000。每个种子和因子对至少进行了1200万次唯一的碰撞测试。运行大约7小时后,最好对发现(其中种子和因子均被限制为4位数字或更少)为:seed = 1009,factor = 9176,用0.1131%的碰撞率。在5位和6位数字区域,甚至存在更好的选择。但是为了简洁起见,我选择了性能最高的4位数字,并且在所有常见int和char哈希情况下,它的表现都很好。对于更大的整数,它似乎也可以正常工作。值得注意的是,“成为主要人物”似乎并不能作为取得种子和/或因素良好表现的一般先决条件,尽管它可能会有所帮助。1009上面提到的实际上是素数,但9176不是。我明确测试了这种变化,在factor附近9176(离开seed = 1009)更改为各种素数,它们的表现都比上述解决方案差。最后,我还对比了通用的ReSharper推荐功能系列hash = (hash * factor) ^ i;和CustomHash()上面提到的原始功能严重胜过它。对于常见的用例假设,ReSharper XOR样式的冲突率似乎在20%至30%的范围内,我认为不应使用。