这是一个“足够好”的随机算法;为什么isn ‘t it used if it’更快?

问题:

我做了一个叫QuickRandom的类,它的工作是快速产生随机数。这很简单:只要取旧值,乘以double,取小数部分。
这是我的QuickRandom类的全部:

public class QuickRandom {
    private double prevNum;
    private double magicNumber;

    public QuickRandom(double seed1, double seed2) {
        if (seed1 >= 1 || seed1 < 0) throw new IllegalArgumentException("Seed 1 must be >= 0 and < 1, not " + seed1);
        prevNum = seed1;
        if (seed2 <= 1 || seed2 > 10) throw new IllegalArgumentException("Seed 2 must be > 1 and <= 10, not " + seed2);
        magicNumber = seed2;
    }

    public QuickRandom() {
        this(Math.random(), Math.random() * 10);
    }

    public double random() {
        return prevNum = (prevNum*magicNumber)%1;
    }

}
&#91;/code&#93;
这里是我写的测试代码:
&#91;code lang="python"&#93;
public static void main(String&#91;&#93; args) {
        QuickRandom qr = new QuickRandom();

        /*for (int i = 0; i < 20; i ++) {
            System.out.println(qr.random());
        }*/

        //Warm up
        for (int i = 0; i < 10000000; i ++) {
            Math.random();
            qr.random();
            System.nanoTime();
        }

        long oldTime;

        oldTime = System.nanoTime();
        for (int i = 0; i < 100000000; i ++) {
            Math.random();
        }
        System.out.println(System.nanoTime() - oldTime);

        oldTime = System.nanoTime();
        for (int i = 0; i < 100000000; i ++) {
            qr.random();
        }
        System.out.println(System.nanoTime() - oldTime);
}
&#91;/code&#93;
这是一个非常简单的算法,简单地将以前的双倍乘以“魔术数”双倍。我把它扔在一起很快,所以我可以做得更好,但奇怪的是,它似乎工作正常。
这是<code>main</code>方法中注释掉的行的示例输出:

0.612201846732229
0.5823974655091941
0.31062451498865684
0.8324473610354004
0.5907187526770246
0.38650264675748947
0.5243464344127049
0.7812828761272188
0.12417247811074805
0.1322738256858378
0.20614642573072284
0.8797579436677381
0.022122999476108518
0.2017298328387873
0.8394849894162446
0.6548917685640614
0.971667953190428
0.8602096647696964
0.8438709031160894
0.694884972852229

嗯。漂亮的随机事实上,这将适用于游戏中的随机数发生器。
以下是未注释部分的示例输出:

5456313909
1427223941

哇!它的运行速度比Math.random快4倍
我记得阅读Math.random使用System.nanoTime()和大量疯狂模数和分数的地方。真的有必要吗?我的算法执行得更快,看起来很随机。
我有两个问题:

  • 我的算法“足够好”(比如,一个游戏,随机数不是太重要)?
  • 为什么Math.random这样做很多,只是简单的乘法和切出小数就足够了?

回答:

您的QuickRandom实施并不是一个统一的分布。频率通常较低,而Math.random()具有更均匀的分布。这是一个SSCCE,显示:

package com.stackoverflow.q14491966;

import java.util.Arrays;

public class Test {

    public static void main(String[] args) throws Exception {
        QuickRandom qr = new QuickRandom();
        int[] frequencies = new int[10];
        for (int i = 0; i < 100000; i++) {
            frequencies&#91;(int) (qr.random() * 10)&#93;++;
        }
        printDistribution("QR", frequencies);

        frequencies = new int&#91;10&#93;;
        for (int i = 0; i < 100000; i++) {
            frequencies&#91;(int) (Math.random() * 10)&#93;++;
        }
        printDistribution("MR", frequencies);
    }

    public static void printDistribution(String name, int&#91;&#93; frequencies) {
        System.out.printf("%n%s distribution |8000     |9000     |10000    |11000    |12000%n", name);
        for (int i = 0; i < 10; i++) {
            char&#91;&#93; bar = "                                                  ".toCharArray(); // 50 chars.
            Arrays.fill(bar, 0, Math.max(0, Math.min(50, frequencies&#91;i&#93; / 100 - 80)), '#');
            System.out.printf("0.%dxxx: %6d  :%s%n", i, frequencies&#91;i&#93;, new String(bar));
        }
    }

}
&#91;/code&#93;
平均结果如下所示:
class="lang-none prettyprint-override">
QR distribution |8000     |9000     |10000    |11000    |12000
0.0xxx:  11376  :#################################                 
0.1xxx:  11178  :###############################                   
0.2xxx:  11312  :#################################                 
0.3xxx:  10809  :############################                      
0.4xxx:  10242  :######################                            
0.5xxx:   8860  :########                                          
0.6xxx:   9004  :##########                                        
0.7xxx:   8987  :#########                                         
0.8xxx:   9075  :##########                                        
0.9xxx:   9157  :###########                                       

MR distribution |8000     |9000     |10000    |11000    |12000
0.0xxx:  10097  :####################                              
0.1xxx:   9901  :###################                               
0.2xxx:  10018  :####################                              
0.3xxx:   9956  :###################                               
0.4xxx:   9974  :###################                               
0.5xxx:  10007  :####################                              
0.6xxx:  10136  :#####################                             
0.7xxx:   9937  :###################                               
0.8xxx:  10029  :####################                              
0.9xxx:   9945  :###################    

如果重复测试,您将看到QR分布变化很大,取决于初始种子,而MR分布是稳定的。有时它达到所需的均匀分布,但比通常没有。这是一个更极端的例子,它甚至超出了图形的边界:
class="lang-none prettyprint-override">

QR distribution |8000     |9000     |10000    |11000    |12000
0.0xxx:  41788  :##################################################
0.1xxx:  17495  :##################################################
0.2xxx:  10285  :######################                            
0.3xxx:   7273  :                                                  
0.4xxx:   5643  :                                                  
0.5xxx:   4608  :                                                  
0.6xxx:   3907  :                                                  
0.7xxx:   3350  :                                                  
0.8xxx:   2999  :                                                  
0.9xxx:   2652  :                                                  

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Is this a “good enough” random algorithm; why isn't it used if it's faster?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

68 − = 62