java.util.Random有多好?
两个问题:
我会为每个种子input不同的数字序列吗?
有没有一些“死”的种子? (产生零点或重复速度非常快的单元)
顺便说一下,我应该使用哪些PRNG?
解决scheme:因为我将要使用PRNG来制作游戏,所以我不需要密码保护。 我正在和Mersenne Twister一起,因为它的速度和巨大的时期。
在某种程度上,随机数发生器是马匹的课程。 随机类使用合理select的参数来实现LCG。 但它仍然具有以下特点:
- 相当短的时间(2 ^ 48)
- 位不是同样随机的(参见我的关于位位置的随机性的文章)
- 只会产生一小部分价值组合 (着名的问题“ 落在飞机上 ”)
如果这些东西对你无关紧要,那么Random就具有作为JDK一部分提供的补偿function。 休闲游戏(但不包括涉及金钱的游戏)就足够了。 没有脆弱的种子。
XORShift生成器的另一种替代方法,可以用Java实现如下:
public long randomLong() { x ^= (x << 21); x ^= (x >>> 35); x ^= (x << 4); return x; }
对于一些非常便宜的操作,这有一个2 ^ 64-1(不允许为零)的时间段,并且当您重复生成值时足够简单,可以内联。 可能有不同的移位值:请参阅George Marsaglia关于XORShift生成器的文章以获取更多详细信息。 您可以将生成的数字中的位视为同等随机。 一个主要的弱点是,偶尔它会进入一个“车辙”,在这个数字中没有多less比特被设置,然后需要几代才能走出这个车辙。
其他可能性是:
- 组合不同的发电机(例如,将来自XORShift发电机的输出馈入LCG,然后将结果添加到具有不同参数的XORShift发电机的输出):这通常允许不同方法的弱点被“平滑”,并且可以如果仔细select组合发电机的周期,可以给出更长的时间
- 添加一个“滞后”(给一个更长的时间段):本质上,发生器通常会转换生成的最后一个数字,存储一个“历史缓冲区”并转换,例如(n-1023)。
我会说避免使用一个愚蠢的内存量的发生器给你一个比你真正需要的时间更长的时间(有些人的周期比宇宙中的primefaces数多 – 你通常不需要这个)。 注意“长周期”并不一定意味着“高质量的发电机”(虽然2 ^ 48仍然有点低!)。
正如zvrba所说,JavaDoc解释了正常的实现。 伪随机数发生器上的维基百科页面有相当多的信息,并提到了Mersenne twister ,它不被认为是密码安全的,但速度非常快, 在Java中有各种实现 。 (最后一个链接有两个实现 – 我相信还有其他的可用的。)
如果您需要encryption安全生成,请阅读维基百科页面 – 有多种可用选项。
随着RNG的发展,Sun的实施绝对不是现成的 ,但对于大多数目的来说已经足够了。 如果您需要随机数字用于encryption目的,那么就有java.security.SecureRandom ,如果您只想要比java.util.random更快更好的东西,则可以很容易地在网上findMersenne Twister的Java实现。
这在文档中有描述。 线性同余发生器在理论上已经被很好地理解,并且在文献和因特网上有大量的材料可用。 具有相同参数的线性同余发生器总是输出相同的周期序列,种子决定的唯一事情就是序列开始的地方。 所以你的第一个问题的答案是“是的,如果你产生足够的随机数字”。
在我的博客文章中查看答案:
http://code-o-matic.blogspot.com/2010/12/how-long-is-period-of-random-numbers.html
随机对于其状态(长期的,即2 ^ 64周期)具有最大周期。 这可以直接推广到2 ^ k – 如你所愿地投资尽可能多的状态位,并获得最大周期。 2Mersenne Twister实际上是一个很短的时期,比较(见上述博文中的评论)。
–Oops。 随机将自身限制为48位,而不是使用长整个64位,所以相应地,它的周期毕竟是2 ^ 48,而不是2 ^ 64。
如果RNG质量真的对你很重要,我build议使用你自己的RNG。 也许java.util.Random在这个版本中,在你的操作系统上是很棒的。 但是这可能会改变。 之前发生的事情是,图书馆作者在后来的版本中使事情变得更糟。
编写自己的代码非常简单,然后你就知道到底发生了什么。 它不会在升级时发生变化,等等。这是一个您可以在10分钟内移植到Java的生成器 。 如果你从现在开始用一种新语言开始写,你可以再次移植它。
如果你没有实现你自己的,你可以从一个有信誉的来源获取一个知名的RNG代码,并将其用于你的项目。 那么没有人会改变你的发电机。
(我不是主张人们自己提出algorithm ,只是自己实现 ,大多数人,包括我自己在内,都没有开发自己的algorithm,很容易写出一个你认为是好的坏的生成器,这就是为什么人们需要提问这样的问题,想知道库生成器有多好,我引用的生成器中的algorithm经过了很多同行评审。