![](/img/trans.png)
[英]Java - Implementing a random vector generator that produces normally distributed numbers
[英]Normally distributed random integers?
是否有一种很好的方法来获得具有正态分布的随机生成的整数?
我想到的第一种方法:
int rndi = (int)Math.floor(random.nextGaussian()*std);
有没有更好的办法?
严格来说,你不能拥有正态分布的整数。 也许你想要的是分配到桶中的正态分布的输出。 在这种情况下,您可能希望根据数组的大小来移动和缩放正态分布。 如果您只是从标准正态分布(均值= 0和比例= 1)中取样,您将在99%的时间内得到介于-2和2之间的样本。
假设您需要来自大小为N的数组的随机样本。您希望中间的条目比最后的样本更频繁地选择,但您希望偶数附近的样本偶尔出现,比如1%的时间。 然后你可能想要计算N / 2 + N * z / 4之类的东西,其中z是你的标准法线,然后将这些数字转换为整数。 如果你这样做,你偶尔会在阵列外得到一个索引。 只需测试它,并在发生这种情况时获得新值。
您应该更新问题以明确您的用例是什么。
根据你的评论,你根本不应该使用正态分布。 而是尝试许多离散分布中的一个,因为你最后想要整数。 有很多这些,但我推荐一个 - 非常简单。 它使用随机向量作为离散概率分布。
这是一个示例实现:
public class DiscreteRandom {
private final double[] probDist;
public DiscreteRandom(double... probs) {
this.probDist = makeDistribution(probs);
}
private double[] makeDistribution(double[] probs) {
double[] distribution = new double[probs.length];
double sum = 0;
for (int i = 0; i < probs.length; i++) {
sum += probs[i];
distribution[i] = sum;
}
return distribution;
}
public int nextInt() {
double rand = Math.random();
int i = 0;
while (rand > probDist[i]) i++;
return i;
}
/**
* Simple test
*/
public static void main(String[] args) {
// We want 0 to come 3 times more often than 1.
// The implementation requires normalized probability
// distribution thus testProbs elements sum up to 1.0d.
double[] testProbs = {0.75d, 0.25d};
DiscreteRandom randGen = new DiscreteRandom(testProbs);
// Loop 1000 times, we expect:
// sum0 ~ 750
// sum1 ~ 250
int sum0 = 0, sum1 = 0, rand;
for (int i = 0; i < 1000; i++) {
rand = randGen.nextInt();
if (rand == 0) sum0++;
else sum1++;
}
System.out.println("sum0 = " + sum0 + "sum1 = " + sum1);
}
}
这取决于你试图用这些随机数做什么。
java.util.Random
有一些缺陷。 如JavaDoc中所述, nextGaussian()
方法使用Box Muller变换。 它取决于使用线性同Random.nextDouble()
器实现的Random.nextDouble()
。 并且实现不是最好的,如错误修正提议中所述:
Sun的方法使用48位种子(就底部位而言)仅访问17位 - 产生极其严重的非随机性 。
因此,如果您对高统计质量感兴趣,那么您应该真正避免Sun的实施。 看看这个“不那么随机”的小程序,用于视觉证明它有多糟糕。
如果统计质量是您关注的问题,那么您可以做的最好的事情就是使用一些外部PRNG库。
您可以预先计算“随机”整数列表,然后手动调整该列表以获得所需的分布。
然后,当你想要一个“随机”数字时,只需从列表中提取下一个可用数字......
这样,您可以确保分布,从而确保选择特定项目的概率。 为了好玩,您可以随时“混淆”您的列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.