当前位置: 首页 > 编程语言 > C#

如何选择质数来计算哈希码?分享

时间:2023-04-10 22:25:22 C#

如何选择质数来计算哈希码?这个问题遵循JonSkeet对这个问题给出的答案:“What'sthebestalgorithmtooverrideSystem.Object.GetHashCode?”。要计算哈希码,请使用以下算法:publicoverrideintGetHashCode(){unchecked//溢出没问题,只是wrap{inthash=17;//适当的无效检查等,当然:)hash=hash*23+field1.GetHashCode();hash=hash*23+field2.GetHashCode();hash=hash*23+field3.GetHashCode();返回散列;我不明白为什么选择数字17和23。我们为什么不选择3和5?这也是一个素数。有人可以解释什么是最佳质数以及为什么吗?您链接到的答案的评论已经简要地试图解释为什么17和23不是在这里使用的好素数。许多使用散列码的.NET类将元素存储在桶中。假设有三个桶。然后哈希码为0,3,6,9...的所有对象存储在桶0中。哈希码为1,4,7,10...的所有对象存储在桶1中。桶2,5中的所有对象,8,11...存储在存储桶2中。现在假设您的GetHashCode()使用hash=hash*3+field3.GetHashCode();.这意味着除非散列足够大以便乘法环绕,否则在具有三个桶的散列集中,对象将最终进入哪个桶仅取决于field3。由于对象在桶中的分布不均匀,HashSet无法提供良好的性能。您需要一个包含所有可能数量的桶的因子。出于同样的原因,桶数本身将是素数,因此如果您的因子是素数,唯一的风险是它等于桶数。.NET使用一个固定的允许桶数列表:publicstaticreadonlyint[]primes={3,7,11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919,1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10203,1,5,241,22430293,36353,43627,52361,62851,75431,90523,108631,130363,156437,187751,225307,270371,324449,389357,467237,560689,672827,807403,968897,1162687,1395263,1674319,2009191,2411033,2893249,3471899,4166287,4999559,5999471,7199369};您的因素应该是.NET不使用的因素,并且其他自定义实现同样不太可能使用。这意味着23是一个坏因素。31可以使用.NET自己的容器,但对于自定义实现来说可能同样糟糕。同时,它不应该太低,以至于它给普通使用带来了很大的冲击。这是3和5的风险:假设您有一个包含许多小整数的自定义Tuple实现。请记住,int.GetHashCode()仅返回int本身。假设您的乘数是3。这意味着(0,9)、(1,6)、(2,3)和(3,0)都给出相同的哈希码。这两个问题都可以通过使用足够大的素数来避免,正如JonSkeet在他的回答中引用的评论中指出的那样:经过。显然486187739很好……曾几何时,用于乘法的大素数可能不好,因为大整数的乘法速度足够慢,性能差异很明显。在这种情况下乘以31会很好,因为它可以实现为x*31=>x*32-x=>(x。然而,如今,乘法不太可能导致任何性能问题,然后,一般来说,越大越好,以上是C#学习教程:如何选择质数来计算哈希码?全部内容分享,如果对大家有用,还需要详细了解C#学习教程,希望大家多多指教多多关注---本文来自网络收藏,不代表立场,如涉及侵权,请点击右边联系管理员删除,转载请注明出处: