说我需要在[0,K)范围内的N个密码安全的伪随机整数。实现此目的最明显的方法是对arc4random_uniform(3)
进行N次调用,而这正是我正在做的事情。
但是,探查器告诉我,对arc4random_uniform(3)
的多次调用占用了整个执行时间的2/3,我确实需要使我的代码更快。这就是为什么我计划预先生成一些随机字节(可能使用arc4random_buf(3)
),然后一点一点地从中提取。
对于K = 2,我可以简单地屏蔽掉所需的位,但是当K不是2的幂时,事情就会变得多毛。当然,我可以使用一堆%=
和/=
,但是那样我会产生模偏差。另一个问题是,当N太大时,我将无法再将整个缓冲区解释为整数并对其执行算术运算。
在有意义的情况下,K会小于20,而N可能会非常大,例如数百万。
答案 0 :(得分:3)
您可以使用模运算符和除法,只需要做一些额外的预处理即可。正常生成值数组。将P
设为K
的最大乘方,小于或等于2^32
(其中^
表示幂),并遍历数组以确保所有随机值严格少于P
。如果不是,则替换为小于P
的新随机数。这样可以消除偏差。
现在要处理大型N
,您将需要两个循环。第一个循环遍历数组中的元素,第二个循环从每个元素中提取多个随机数。如果为P = k ^ e
,则可以从数组中每个元素的e
中提取[0, k)
个随机数。每次从元素提取随机数时,请对该元素进行k
的底数除法。
当然,这不一定是实际的循环。您可以存储两个变量(数组索引,子元素索引),并在调用函数时从array_index
元素中提取。如果为sub_element_index == e
,则将其重置为零并增加array_index
。从该数组元素中提取一个随机数,然后返回它。