当前位置:  开发笔记 > 编程语言 > 正文

java.util.Random有多好?

如何解决《java.util.Random有多好?》经验,为你挑选了3个好方法。

两个问题:

我会为每个种子获得不同的数字序列吗?

是否有一些"死"的种子?(产生零或快速重复的那些.)

顺便说一句,我应该使用哪些其他PRNG?

解决方案:因为,我将使用PRNG来制作游戏,我不需要它在加密方面是安全的.我要和Mersenne Twister一起去,因为它的速度和时间很长.



1> Neil Coffey..:

在某种程度上,随机数发生器是课程的马匹.Random类使用合理选择的参数实现LCG.但它仍然具有以下特点:

相当短的时期(2 ^ 48)

位不是同等随机的(参见我关于位位置随机性的文章)

只会产生一小部分价值组合(着名的" 落在飞机上 ")

如果这些事情对您无关紧要,则Random具有作为JDK的一部分提供的兑换功能.这对于休闲游戏(但不包括涉及金钱的游戏)来说已经足够了.这样没有弱种子.

另一个替代方案是XORShift生成器,可以用Java实现如下:

public long randomLong() {
  x ^= (x << 21);
  x ^= (x >>> 35);
  x ^= (x << 4);
  return x;
}

对于一些非常便宜的操作,它的周期为2 ^ 64-1(不允许为零),并且当您重复生成值时,它很简单,可以内联.各种移位值都是可能的:有关详细信息,请参阅George Marsaglia关于XORShift发生器的论文.您可以将生成的数字中的位视为同等随机.一个主要的弱点是偶尔它会进入一个"车辙",其中数字中没有设置很多位,然后需要几代才能摆脱这个车辙.

其他可能性是:

组合不同的发生器(例如,将XORShift发生器的输出馈入LCG,然后将结果添加到具有不同参数的XORShift发生器的输出):这通常允许不同方法的弱点被"平滑",并且可以如果仔细选择组合发电机的周期,则给出更长的时间

添加"滞后"(以给出更长的时间段):基本上,在生成器通常将变换生成的最后一个数字的情况下,存储"历史缓冲区"并转换,例如,(n-1023).

我会说避免使用愚蠢数量的内存的生成器给你一个比你真正需要的更长的时间(有些时间段大于宇宙中的原子数 - 你通常不需要那个).请注意,"长周期"并不一定意味着"高质量发电机"(尽管2 ^ 48仍然有点低!).


不,老实说,它是2 ^ 48 !! 不要相信你在博客中看到的一切 - 看看java.lang.Random的实际源代码!参见以下行:seed =(seed*multiplier + 0xbL)&((1L << 48) - 1);
是的,你是对的,纠正了它.最后错过了面具.无论如何,那里仍然有用的信息 - 期间种子=(种子*乘数+加)是完全不明显的 - 并且基础数学是完全出乎意料的.PS:这是我的博客,我倾向于相信我写的:)
在重复值之前,组合多个生成器实际上是一种结束意外微小循环的好方法.
是! D. Knuth,计算机编程艺术,Vol.2:(3.2.2)"与随机数生成相关的常见谬误之一是我们可以采用一个好的生成器并对其进行一些修改,以获得"更随机"的序列.这通常是错误的......新的序列可能不那么随机.因为整个理论都破裂了,并且在没有关于序列行为的任何理论的情况下......这些序列的表现可能比从更有纪律的功能中获得的序列"

2> Jon Skeet..:

正如zvrba所说,JavaDoc解释了正常的实现.关于伪随机数生成器的维基百科页面有相当多的信息,并提到了Mersenne twister,它不被认为是加密安全的,但速度非常快,并且在Java中有各种实现.(最后一个链接有两个实现 - 我相信还有其他实现.)

如果您需要加密安全生成,请阅读维基百科页面 - 有各种选项可供选择.



3> Michael Borg..:

随着RNG的发展,Sun的实施绝对不是最先进的,但对于大多数用途来说已经足够了.如果您需要随机数用于加密目的,那么有java.security.SecureRandom,如果您只想要比java.util.random更快更好的东西,那么很容易在网上找到Mersenne Twister的Java实现.

推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有