我有一个伪随机数生成器的实现,特别是George Marsaglia的XOR-Shift RNG的实现。我的实现在这里:
FastRandom.cs
事实证明,第一个随机样本与种子紧密相关,如果您查看Reinitialise(int seed)方法,这将非常明显。这不好。我提出的解决方案是如下混合种子的各个位:
_x = (uint)( (seed * 2147483647)
^ ((seed << 16 | seed >> 48) * 28111)
^ ((seed << 32 | seed >> 32) * 69001)
^ ((seed << 48 | seed >> 16) * 45083));
因此,我将种子的位乘以四个素数并进行异或以形成_x,从而显着削弱了任何相关性。在乘法之前,我还旋转种子的位,以确保大小不同的位在32位值的整个值范围内混合在一起。
四向旋转似乎只是在不执行任何操作和每次可能进行的旋转之间取得很好的平衡(32)。质数是“空中的手指”-足够的大小和位结构以使位混乱,并在整个32位上“散布”它们,而不管起始种子是什么。
我应该使用更大的素数吗?是否有解决此问题的标准方法,也许有更正式的依据?我正在尝试以最小的CPU开销执行此操作。
谢谢
===更新===
我决定使用一些质数,将设置的位更好地分布在所有32位中。结果是我可以在乘法达到相同效果时忽略移位(在32位的整个范围内散列位),因此我只需将这四个乘积相加即可得到最终的种子...
_x = (uint)( (seed * 1431655781)
+ (seed * 1183186591)
+ (seed * 622729787)
+ (seed * 338294347));
我可能会得到更少的素数/乘法。两个看起来太少了(我仍然可以在第一个样本中看到模式),三个看起来还可以,因此为了安全起见,我将其设置为四个。
===更新2 ===
仅供参考,以上简化为功能等效:
_x = seed * 3575866506U;
我最初没有发现这一点,当我这样做时,我想知道在计算的不同阶段溢出是否会导致不同的结果。我相信答案是否定的-两种计算总是给出相同的答案。
最佳答案
根据一些研究人员的说法,CrapWow,Crap8和Murmur3是当今可用的最佳非加密哈希算法,它们既快速,简单又在统计上不错。
有关更多信息,请访问Non-Cryptographic Hash Function Zoo。
关于c# - 对Int32或UInt32中的位进行哈希处理的好方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12717413/