【问题标题】:Quality of PRNG when not using all bits at once不一次使用所有位时的 PRNG 质量
【发布时间】:2016-01-05 11:05:31
【问题描述】:

我目前在我的项目中使用 xorshift128+,我知道它通过了 Big Crush,并且被认为可以为它的速度生成相当高质量的随机数。但是,它会生成 64 位数字,而我需要的绝大多数随机数都是小整数(介于 0 和 100 左右之间)。

现在,使用 % 将 64 位随机数减少到所需范围会导致分布不均匀(某些数字出现的次数比其他数字多),并且在 2 的幂的情况下完全丢弃大部分位.生成数字直到某物在范围内的方法会产生更均匀的分布,但是对于小数字会有些问题,而且当我已经有太多的东西开始时生成更多的位感觉很愚蠢。

因此,我实现了一个系统,该系统采用最少的必要位数(寻找最接近的 2 次方,例如,如果我需要 0-95 的范围,我将采用 7 位 (2^7 = 128) 和继续生成 7 位,直到我得到低于 95 的东西,这应该总是有超过 50% 的概率,否则我只能少用一点)

无论如何,该系统已经到位,基本统计测试表明它按预期工作,而且运行速度极快。但是,我无法在修改后的系统上运行 TestU01(似乎没有内置对动态位大小的支持),并且原始论文对我来说有点太密集了。

基本上,我想知道是否像 xorshift128+ 声称的那样向前和向后传递 Big Crush,强烈建议每个单独的位都是令人满意的随机并且单独使用它们应该没问题,或者我是否可以设置自己为了麻烦。另外,可选地,任何可以让我凭经验验证生成器的统计质量的测试套件。

【问题讨论】:

  • 这正是我在 onejoker 库中所做的,而且效果很好。我进行了广泛的测试。
  • 关于经验测试的小问题。使用简单的 64 位模数,对高权重值的偏好是如此之小,以至于您必须收集许多 quintillions 的值才能开始测量具有统计意义的偏差。

标签: algorithm optimization random


【解决方案1】:

生成数字直到某物在范围内的方法会产生更均匀的分布,但对于小数字会有些问题[...]。

对于像以下 C99 示例这样的幼稚实现来说确实如此:

uint64_t prng(void);

// Returns a random number between 0 and max-1.
uint64_t bounded_prng(uint64_t max) {
    uint64_t r;

    // Rejection sampling.
    do {
        r = prng();
    } while (r >= max);

    return r;
}

但还有另一种有效的算法。您可以使用适合uint64_tmax 的最大倍数来扩展阈值,即2^64 - (2^64 % max)。如果 PRNG 返回的值低于此阈值,则返回值模数max,否则获取另一个随机值。

uint64_t bounded_prng(uint64_t max) {
    // Compute modulus: 2^64 % max = (2^64 - max) % max = -max % max.
    uint64_t mod = -max % max;

    // Compute threshold: 2^64 - mod = -mod
    uint64_t threshold = -mod;

    uint64_t r;

    do {
        r = prng();
    } while (r >= threshold);

    return r % max;
}

现在,随机值被拒绝的概率保证小于 50%,从而产生了一个非常有效的算法,就像您的位掩码方法一样。对于小范围,prng 被多次调用的概率非常小。但是,如果您事先知道界限,您的位掩码解决方案可能仍会胜出。

您可以通过拒绝小于阈值的值来稍微优化:

uint64_t bounded_prng(uint64_t max) {
    // Compute threshold: 2^64 % max = (2^64 - max) % max = -max % max.
    uint64_t threshold = -max % max;

    uint64_t r;

    do {
        r = prng();
    } while (r < threshold);

    return r % max;
}

基本上,我想知道是否像 xorshift128+ 声称的那样向前和向后传递 Big Crush,强烈建议每个单独的位都是令人满意的随机并且单独使用它们应该没问题,或者我是否可以设置自己麻烦。

如果您想计算有界随机值,您必须确保消除任何偏差。那么有界随机值的质量应该与原始 PRNG 相匹配。如果你的 PRNG 通过 Big Crush,你肯定会得到高质量的有界随机数。你的方法和我展示的任何方法都很好。

【讨论】:

    【解决方案2】:

    您正在做的是生成均匀分布的 int 的最常用方法,Big Crush 是一个非常好的测试套件。它当然可以确保这些位是单独随机的,以及一大堆你永远不会想到的其他东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 2020-05-06
      • 2018-11-12
      • 1970-01-01
      相关资源
      最近更新 更多