我正在研究python如何实现字典。 python字典实现中的一个等式涉及使用等式
的空字典槽的伪随机探测j = ((j*5) + 1) % 2**i
解释为here。
我已经阅读了这个问题How are Python's Built In Dictionaries Implemented,并且基本上了解了字典是如何实现的。
我不明白为什么/如何使用等式:
j = ((j*5) + 1) % 2**i
循环遍历2**i
的所有余数。例如,如果i = 3
的总起始大小为8. j
,则会在整个周期内完成:
0
1
6
7
4
5
2
3
0
如果起始大小为16,它将经历循环:
0 1 6 15 12 13 2 11 8 9 14 7 4 5 10 3 0
这对于探测字典中的所有插槽非常有用。 但为什么会有效呢?为什么j = ((j*5)+1)
有效但j = ((j*6)+1)
或j = ((j*3)+1)
这两种情况都会陷入较小的周期。
我希望能够更直观地了解这一点,而不是方程式正常运作以及它们使用它的原因。
答案 0 :(得分:13)
与Jasper暗示的伪随机数生成器使用的原理相同,即linear congruential generators。线性同余生成器是遵循关系X_(n+1) = (a * X_n + c) mod m
的序列。来自维基页面,
一般LCG的周期最多为m,而某些因子的选择a远小于此。当且仅当以下情况时,LCG将为所有种子值设置一个完整的期限:
m
和c
相对较为优秀。- 如果
a - 1
可被m
的所有素数因子整除。a - 1
可被m
整除,则- 醇>
4
可被4整除。
很明显,5是满足这些要求的最小a
,即
同样有趣的是,5并不是满足这些条件的唯一数字。 9也会奏效。将m
设为16,使用j=(9*j+1)%16
得出
0 1 10 11 4 5 14 15 8 9 2 3 12 13 6 7
这三个条件的证据可以在第5页的the original Hull-Dobell paper中找到,还有一些其他可能感兴趣的PRNG相关定理。