繁体   English   中英

正态分布的随机整数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM