这是一个“足够好”的随机算法吗?如果它更快,为什么不使用它?
2022-08-31 06:57:27
我创建了一个名为 的类,它的工作是快速生成随机数。这真的很简单:只需取旧值,乘以 a ,然后取小数部分。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;
}
}
这是我为测试它而编写的代码:
public static void main(String[] 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);
}
这是一个非常简单的算法,只需将前一个双精度乘以“幻数”双精度值。我很快就把它拼凑起来了,所以我可能会让它变得更好,但奇怪的是,它似乎工作得很好。
这是该方法中注释掉的行的示例输出:main
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
哇!它的性能几乎比 快 4 倍。Math.random
我记得在某个地方读到过很多疯狂的模量和除法的东西。这真的有必要吗?我的算法执行速度要快得多,而且看起来很随机。Math.random
System.nanoTime()
我有两个问题:
- 我的算法是否“足够好”(例如,对于一个游戏,真正的随机数不太重要)?
- 为什么在看起来只是简单的乘法和切掉小数就足够了的情况下做这么多?
Math.random