关于随机值

3

可能是重复问题:
获取N个随机数,使它们的和为M

你好, 我有一个问题:

如何获得随机值,使它们的总和为1。 例如:{0.5,0.5}{0.25,0.25,0.5}等等。 这些值的数量每次都不同,有时可以是2,有时可以是3,就像上面的例子一样! 谢谢。


3
如果它们必须加起来等于某个值,那么它们就不是完全随机的。 - cdhowie
我有一个包含10000个元素的数组,每个元素都有自己的概率(元素是一个具有两个字段1)数字2)概率的对象),所有概率的总和必须为1!那么我如何在不使用随机的情况下实现这一点? - user472221
2
生成随机数(在0和数组长度之间),并增加所生成数字对应的元素。重复此操作n次。然后,将所有元素除以n,这样你就得到了元素的概率(总和为1)。 - Reese Moore
1
重复:https://dev59.com/kHE85IYBdhLWcg3wvGAR#2640067 - Guillaume
@cdhowie:为什么?你取一个区间(在0和预期总和之间),然后随机放置点在该区间内。告诉我哪里明显不随机。 - Joey
5个回答

12
我将为您概述基本算法:
  • 决定要生成多少个随机数来求和。

  • 生成上述数量的随机数。

  • 确定它们应该相加得到什么数字。

  • 将前一步中的数字除以随机数之和。

  • 将每个随机数除以前一步中的数字。

基本上,您将生成一堆无限制的随机数,然后调整它们使它们加起来等于某个特定数字。
顺便说一句:在极少数情况下,如果您生成的所有随机数都是零,则在使用此算法时会出现除以零错误。因此,在实现中应对此进行捕获,并在循环中重试随机数生成,直到获得非零的随机数总和。

2
+1 - 尽管应该注意到,浮点舍入误差可能意味着这些数字不会完全加起来等于1.0。 - Stephen C
@Stephen C:说得好。希望浮点数舍入误差不会对程序的行为产生重大影响。 - Asaph

1
通常情况下,您可以生成一个随机大小的数组:
    java.util.Random rand = new java.util.Random();
    final int MAX_SIZE = 100;
    double[] a = new double[1 + rand.nextInt(MAX_SIZE)];

(这里我假设您不希望数组大于100个元素。)
然后,您可以使用随机正数填充数组:
    for (int i = 0; i < a.length; ++ i)
    {
        a[i] = rand.nextDouble();
    }

然后您需要对数组进行归一化(将每个元素除以总和)。 首先,我们计算总和:

    double sum = 0.0;
    for (int i = 0; i < a.length; ++ i)
    {
        sum += a[i];
    }

然后将每个数组元素除以总和:
    for (int i = 0; i < a.length; ++ i)
    {
        a[i] /= sum; 
    }

如果您想要更短的代码,可以将累加总和的循环与填充随机正整数数组的循环结合起来。以下是生成的代码:
    java.util.Random rand = new java.util.Random();
    final int MAX_SIZE = 100;
    double[] a = new double[1 + rand.nextInt(MAX_SIZE)];

    double sum = 0.0;
    for (int i = 0; i < a.length; ++ i)
    {
        a[i] = rand.nextDouble();
        sum += a[i];
    }

    for (int i = 0; i < a.length; ++ i)
    {
        a[i] /= sum; 
    }

0

类似@dsg但更短。它允许您指定总和应该是多少。

public static double[] randomDoubles(int size, double sum) {
    double total=0, doubles[]=new double[size];
    for(int i=0;i<size;i++) total += doubles[i] = Math.random();
    for(int i=0;i<size;i++) doubles[i] *= sum/total;
    return doubles;
}

0

对于 n 个随机数怎么样:

r1 = random(0,1)
r2 = random(0, 1-r1)
r3 = random(0, 1-r1-r2)
...
r(n) = 1 - r1-r2-f3...-r(n-1)

0

嗯,我认为最简单的方法是这样的:

生成两个数字:

r1 = new RandomNumber
r2 = 1 - r1

生成三个数字:

r1 = new RandomNumber
r2 = r1 / 2
r3 = 1 - r1
r1 = r1 / 2

我不知道是否有更简单的方法来完成这个任务,上面的代码只是伪代码。


谢谢,但如果我想要有100000个值,使它们的总和为1!我该怎么做? - user472221
在那种情况下,按照Guillaume所说的做。不过你应该在最初的问题中提到这一点,因为3和100000之间有很大的区别。 - npinti
对,你说得对,抱歉问题不够清楚。 - user472221

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接