【发布时间】:2013-06-11 01:59:02
【问题描述】:
我正在尝试实现rand_r 接口的可容忍质量版本,它有一个不幸的接口要求,即它的整个状态存储在unsigned 类型的单个对象中,对我而言,这意味着正好32位。另外,我需要它的输出范围是[0,2³¹-1]。标准解决方案是使用 LCG 并丢弃低位(周期最短),但这仍然会为接下来的几个位留下非常糟糕的周期。
我最初的想法是使用 LCG 的两个或三个迭代来生成输出的高/低或高/中/低位。然而,这种方法并不能保持无偏分布;不是每个输出值都具有相同的频率,而是多次出现,而有些则根本不出现。
由于只有 32 位状态,PRNG 的周期以 2³² 为界,并且为了无偏,如果 PRNG 具有完整周期,则每个值必须恰好输出两次,如果具有完整周期,则必须恰好输出一次周期 2³¹。较短的周期不能没有偏见。
是否有任何知名的 PRNG 算法符合这些标准?
【问题讨论】:
-
保证输出似乎与随机相反,不是吗?
-
伪随机不是随机的。不幸的是,“保证产出”的反面是“有偏见的”。对于像 2^100 这样非常大的时期,只要在经验上与均匀无法区分,那么具有完美输出分布并不是真正必要的,但对于像 2^32 这样的小时期,非均匀性将是一个明显的可观察到的偏差。
-
是的,如果之前返回的值有大约 0.5 GB 的数据,您可以预测周期为 2^32 的 PRNG 的下一个值。这是意料之中的,即使分布不均匀也是如此。如果恰好有 2^32 个状态和 2^32 个输出,并且您已经看到其中的 2^32-1 个,则始终确定最后一个。
-
我删除了我的评论。我不太明白你在说什么,但我想我现在明白了。
-
如何使用 LCG,然后应用安全的 1:1 转换(我建议了一些 here)来改进分布?原则上,这类似于在计数器模式下运行加密算法。