具有概率的随机数

新手上路,请多包涵

我想知道在特定范围内生成随机数的最佳方法(例如在 Java 中)是什么,其中每个数字都有一定的发生概率?

例如

从 [1;3] 中生成具有以下概率的随机整数:

P(1) = 0.2

P(2) = 0.3

P(3) = 0.5


现在我正在考虑在 [0;100] 内生成随机整数并执行以下操作的方法:

如果它在 [0;20] 之内 –> 我得到了我的随机数 1。

如果它在 [21;50] 之内 –> 我得到了我的随机数 2。

如果它在 [51;100] 之内 –> 我得到了我的随机数 3。

你打算说什么?

原文由 marc wellman 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 421
2 个回答

你的已经是一个很好的方法并且适用于任何范围。

试想:另一种可能是通过乘以一个常量乘数来去掉分数,然后用这个乘数的 大小 构建一个数组。乘以 10 得到

P(1) = 2
P(2) = 3
P(3) = 5

然后创建一个具有相反值的数组——“1”进入元素 1 和 2,“2”进入 3 到 6,依此类推:

P = (1,1, 2,2,2, 3,3,3,3,3);

然后你可以从这个数组中选择一个随机元素。


(添加。)使用 kiruwka 评论中示例中的概率:

 int[] numsToGenerate           = new int[]    { 1,   2,    3,   4,    5   };
double[] discreteProbabilities = new double[] { 0.1, 0.25, 0.3, 0.25, 0.1 };

导致全整数的最小乘数是 20,这给了你

2, 5, 6, 5, 2

因此 numsToGenerate 的长度为 20,具有以下值:

 1 1
2 2 2 2 2
3 3 3 3 3 3
4 4 4 4 4
5 5

分布 _完全相同_:例如,现在出现“1”的概率是 20 次中有 2 次——仍然是 0.1。

这是基于所有加起来为 1 的原始概率。如果不是,则将总数乘以相同的因子(这也将是您的数组长度)。

原文由 Jongware 发布,翻译遵循 CC BY-SA 3.0 许可协议

前段时间我写了一个帮助类来解决这个问题。源代码应该足够清楚地显示概念:

 public class DistributedRandomNumberGenerator {

    private Map<Integer, Double> distribution;
    private double distSum;

    public DistributedRandomNumberGenerator() {
        distribution = new HashMap<>();
    }

    public void addNumber(int value, double distribution) {
        if (this.distribution.get(value) != null) {
            distSum -= this.distribution.get(value);
        }
        this.distribution.put(value, distribution);
        distSum += distribution;
    }

    public int getDistributedRandomNumber() {
        double rand = Math.random();
        double ratio = 1.0f / distSum;
        double tempDist = 0;
        for (Integer i : distribution.keySet()) {
            tempDist += distribution.get(i);
            if (rand / ratio <= tempDist) {
                return i;
            }
        }
        return 0;
    }

}

该类的用法如下:

 DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator();
drng.addNumber(1, 0.3d); // Adds the numerical value 1 with a probability of 0.3 (30%)
// [...] Add more values

int random = drng.getDistributedRandomNumber(); // Generate a random number

测试驱动程序以验证功能:

     public static void main(String[] args) {
        DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator();
        drng.addNumber(1, 0.2d);
        drng.addNumber(2, 0.3d);
        drng.addNumber(3, 0.5d);

        int testCount = 1000000;

        HashMap<Integer, Double> test = new HashMap<>();

        for (int i = 0; i < testCount; i++) {
            int random = drng.getDistributedRandomNumber();
            test.put(random, (test.get(random) == null) ? (1d / testCount) : test.get(random) + 1d / testCount);
        }

        System.out.println(test.toString());
    }

此测试驱动程序的示例输出:

 {1=0.20019100000017953, 2=0.2999349999988933, 3=0.4998739999935438}

原文由 trylimits 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题