Random 最佳伪随机数发生器

Random 最佳伪随机数发生器,random,Random,到今天为止,哪一个是最好的伪随机数生成器?最好 我是说那个- 通过所有统计测试 即使在非常高的维度上也表现良好 有一个非常大的周期 我能想到MT。有比MT更好的PRNG吗?MT的哪种变体最好?MT似乎通过了您的标准: 它的巨大时期是219937年−1次迭代(>43×106000),被证明在(最多)623维(对于32位值)中是等分布的,并且比其他统计上合理的生成器运行得更快 () Mersenne捻线机是现有测试最广泛的随机数发生器之一。然而,由于它是完全确定的,因此并不适用于所有目的,并且完全不

到今天为止,哪一个是最好的伪随机数生成器?最好 我是说那个-

  • 通过所有统计测试
  • 即使在非常高的维度上也表现良好
  • 有一个非常大的周期

  • 我能想到MT。有比MT更好的PRNG吗?MT的哪种变体最好?

    MT似乎通过了您的标准:

    它的巨大时期是219937年−1次迭代(>43×106000),被证明在(最多)623维(对于32位值)中是等分布的,并且比其他统计上合理的生成器运行得更快

    ()

    Mersenne捻线机是现有测试最广泛的随机数发生器之一。然而,由于它是完全确定的,因此并不适用于所有目的,并且完全不适用于加密目的

    ()

    如果您感兴趣的话,还可以谈谈加密安全的prng。

    试试MT的继任者:SFMT()。首字母缩略词表示面向SIMD的快速梅森捻线机。 它使用向量指令, 与SSE或AltiVec一样,用于加快随机数生成

    此外,它显示的周期比原始MT大:SFMT可以配置为使用高达2216091-1的周期

    最后,MT在初始化不好时遇到了一些问题:它倾向于抽签0,导致质量不好的随机数。该问题可能会持续多达700000次绘制,然后通过算法的重复性进行补偿。因此,SFMT也被设计成比其前身更快地离开这种零过剩状态

    请查看我在本文开头给出的链接,查找描述该算法的源代码和科学出版物

    为了明确地说服您,您可以在这里看到一个比较MT和SFMT生成速度的表格。在任何情况下,SFMT都比MT更快,同时表现出更好的质量

    --编辑以下评论--

    更一般地说,在选择PRNG时,需要考虑正在开发的应用程序。事实上,一些PRNG更适合某些应用程序约束。例如,MT和WELL生成器不太适合于加密应用,但它们是处理蒙特卡罗模拟时的最佳选择

    在我们的例子中,由于其比SFMT更好的等分布特性,WELL似乎是理想的。尽管如此,WELL的速度也要慢得多,他无法显示像SFMT那样大的周期


    作为结论,PRNG不能说对所有应用都是最好的,但对特定领域和特定环境来说是最好的。

    好吧,这是MT-19937的推广和改进。

    如果你寻找一种算法,它通过了所有统计测试,但仍然很快,你可以尝试。与Java中的随机库相比,它大约快30%,并且提供了更好的结果。它的周期没有梅森龙卷风的周期长,但仍然很不错

    可以在此处找到一个实现:

    编辑

    似乎XORShift的新变种现在甚至在质量上击败了MerseneTwister(但在时间上没有)。他们通过了更多的实证质量测试,这一点可以从图表中看出

    他们的表现也令人印象深刻。 我在这里对不同的Java实现、源代码和结果进行了基准测试:

  • 通过所有统计测试
  • 到目前为止,其他回复中提到的每个PRNG都广泛属于GFSR/LFSR PRNG家族。它们都没有通过二进制矩阵秩和可能的线性复杂度测试

    有许多PRNG通过了所有的通用统计测试,但出于某种原因,人们似乎发现GFSR更性感

    以下是一个通过所有通用统计测试但不具有加密安全性的PRNG示例:

    static unsigned long long rng_a, rng_b, rng_c, rng_counter;
    unsigned long long rng64() {
        unsigned long long tmp = rng_a + rng_b + rng_counter++;
        rng_a = rng_b ^ (rng_b >> 12);
        rng_b = rng_c + (rng_c << 3);
        rng_c = ((rng_c << 25) | (rng_c >> (64-25))) + tmp;
        return tmp;
    }
    void seed(unsigned long long s) {
        rng_a = rng_b = rng_c = s; rng_counter = 1;
        for (int i = 0; i < 12; i++) rng64();
    }
    
    static unsigned long long rng_a、rng_b、rng_c、rng_计数器;
    无符号长rng64(){
    无符号长tmp=rng_a+rng_b+rng_计数器++;
    rng_a=rng_b^(rng_b>>12);
    rng_b=rng_c+(rng_c(64-25))+tmp;
    返回tmp;
    }
    无效种子(无符号长s){
    rng_a=rng_b=rng_c=s;rng_计数器=1;
    对于(int i=0;i<12;i++)rng64();
    }
    
    (假设long-long是一个64位整数类型……我认为在定义该类型的任何地方都是如此?)

    这对于任何正常使用都是足够的,而且速度也相当快。如果你需要更好的东西,就换成CSPRNG——它们往往比任何非加密PRNG都要好得多。例如,ChaCha()是一个可靠的CSPRNG,具有快速种子、随机访问和可调质量。HC-256()是一种更高质量的CSPRNG,播种速度慢,但播种后速度相当快

  • 即使在非常高的维度上也表现良好
  • 这相当于第1点。此外,我提供的例子PRNG是混沌类型的——当这些PRNG行为不当时,它们是在小维度上进行的,而不是在大维度上

  • 有一个非常大的周期
  • 定义非常大

    上面提供的示例PRNG I的可证明最小周期为2^64,平均周期为2^255,状态空间为2^256。对于我链接的两个CSPRNG,ChaCha的周期为2^68,状态空间为2^260,HC-256的平均周期约为2^65000 IIRC,并提供了一个概率证明,其最短周期长于2^128,可能性大于1-(2^-128),状态空间约为2^65000

    在实践中,超过大约2^60时,周期并不重要,即使是这一点也无关紧要。通常,人们要求高周期的原因是,要么他们不知道自己在说什么,要么因为他们需要一个大的状态空间(至少与周期相等,但通常更大),这可能会有利于高达2^250左右。但是一个大的状态空间并没有多大帮助