在阅读了一些帖子后,我发现在Java中使用Math.random()来生成一个整数是有偏见的。
我在这篇文章中遇到了一个算法:
Unbiased random number generator using a biased one
它生成一个介于0和1之间的无偏结果,我想在我的程序中使用它。
然而,我正在尝试在Java中创建一个介于0和某个值(例如7)之间的无偏生成器,但我不确定这个算法是否适用于一定范围的数字。
如果没有,我必须做什么才能创建一个我想要的无偏整数生成器?
发布于 2013-06-19 02:16:56
您需要引用声称Java Math.random()有偏见的参考资料,以及具体是什么方面的偏见。这将是一个巨大的问题,因为这是Java标准库的一个非常核心的部分。
Java提供了SecureRandom,它更适合于密码强度的随机数生成。要使用它来生成一个介于0和N之间的数字,您可以使用Random.nextInt(int) documentation中提供的相同算法,但使用的是SecureRandom。
不要实现你自己的随机数生成器算法,除非你愿意不厌其烦地证明它比股票算法更好。创建一个高质量的算法是非常困难的,而且你很可能只会使问题变得更糟。
发布于 2013-06-19 02:01:36
您可以只使用Random.nextInt(int)。根据您的需要,使用new Random().nextInt(8)。正如文档中所说的:
返回一个伪随机的、均匀分布的int值,介于0(包括)和指定的值(不包括)之间
但实际上,我认为您可以一直使用Math.random()。Its documentation says
第一次调用此方法时,它会创建一个新的伪随机数生成器,与表达式
new java.util.Random完全相同
Math.random()的源代码如下:
public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}nextDouble的documentation还说:
返回下一个伪随机、均匀分布的双精度值,介于0.0和1.0
之间
发布于 2013-06-19 02:03:55
我相信你误读了那些帖子,。你链接的那个,本质上是说,你不应该使用 random.nextInt() % max,,这确实是有偏见的;所以这种方法非常幼稚。但是,如果您查看文档或Javas nextInt(max)函数的源代码,就会发现它比这更聪明。可能对你来说足够公正了。了解更多关于Java API的知识,它有很多功能……
详细讨论的示例以无偏的方式生成单比特,而不是0和1之间的无偏双随机!
我不相信Java随机生成器会像你所关心的那样有本质上的偏见。但它肯定不是一个高质量的随机数,因为它需要对大多数用户来说是快速的。如果你想要一个高熵的随机数,试着使用你操作系统的高质量的随机数源。
无论哪种方式,如果你想要一个从0到7的随机数,使用从你的帖子链接的方法(这可能完全是夸大其词!),请执行以下操作:
int bit1 = generateOneBitOfRandom();
int bit2 = generateOneBitOfRandom();
int bit3 = generateOneBitOfRandom();
int zerotoseven = (bit1 << 2) + (bit2 << 1) + bit3;
// Probably at least as good is the proper Java API:
Random random = new Random();
int zerotoseven2 = random.nextInt(8);同样,最有可能的是,java.util.Random nextInt(8)对您来说已经足够好了。除非你在做密码学。然后,如果你的CPU或主板有这样的特性,你真的应该考虑从/dev/random读取一个字节,它可能正在访问硬件熵池(只希望其中一个不会有偏差/偏差被取消)。这很可能是Javas SecureRandom所做的。再举一个例子,说明Java API可能比您想象的要聪明得多。
https://stackoverflow.com/questions/17175573
复制相似问题