在阅读了一些帖子之后,我发现在Java中使用Math.random()
来生成整数是有些偏见的。
我在这篇文章中遇到了一个算法:
Unbiased random number generator using a biased one
它生成0到1之间的无偏结果,我想将它用于我的程序。
但是,我正在尝试在Java中创建一个介于0和某个值(例如7)之间的无偏生成器,但我不确定该算法是否适用于一系列数字。
如果没有,为了创建一个我想要的无偏整数生成器,我该怎么做?
答案 0 :(得分:4)
您需要引用声称Java Math.random()
有偏见的引用,以及确切的方式。这将是一个巨大的问题,因为这是Java标准库的核心部分。
Java提供SecureRandom,它更适合加密强度随机数生成。要使用它来生成介于0和N之间的数字,您可以使用Random.nextInt(int) documentation中提供的相同算法,但使用SecureRandom。
不要实施自己的随机数生成器算法,除非您愿意去解决问题以证明它比库存更好。创建一个高质量的算法非常困难,你很可能只会让问题变得更糟。
答案 1 :(得分:2)
您可以使用Random.nextInt(int)。根据您的需求,使用new Random().nextInt(8)
。正如文档中所述:
返回0(包括)和指定值(不包括)之间的伪随机,均匀分布的 int值
但实际上,我认为你可以一直使用Math.random()
。 Its documentation says:
首次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式
一样new java.util.Random
Math.random()
的源代码是:
public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}
nextDouble
的{{3}}也说:
返回下一个伪随机数,均匀分布在0.0和1.0之间的双重值
答案 2 :(得分:2)
我相信你误读了那些帖子。你链接的那个人基本上说你不应该使用random.nextInt() % max
,这确实是有偏见的;所以这种方法非常幼稚。但是,如果你看一下Javas nextInt(max)
函数的文档或源代码,那么 比那更聪明。可能无偏见给你。只需了解Java API的更多信息,它就有很多功能......
详细讨论的示例以无偏的方式生成单个位,不 0到1之间的无偏双重随机!
我不相信Java随机生成器会以您所关注的方式存在偏差。但它肯定不是高质量的随机数,因为对于大多数用户来说它需要 fast 。如果您想要高熵随机,请尝试使用操作系统的高质量随机源。
无论哪种方式,如果你想要一个从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)
对你来说已经足够了。除非您正在进行加密。那么你真的应该考虑从/dev/random
读取一个字节,如果你的CPU或主板有这样的功能(只希望一个没有偏置/偏置取消),它可能正在访问硬件熵池。这最有可能是Javas SecureRandom
所做的。再一个例子,Java API可能比你想象的更聪明。
答案 3 :(得分:1)
试试这个:
int randomizer(int min, int max)
{
int n = max - min + 1;
int remainder = RAND_MAX % n;
int x;
do
{
x = rand();
} while (x >= RAND_MAX - remainder);
return min + x % n;
}
它是您链接到的其他算法的修改版本。
答案 4 :(得分:-1)
如果只能从0到1工作,只需将它给你的任意乘以7,你就会得到一个0到7的无偏随机数。