如何生成总和为预定值的N个随机值?

时间:2011-04-30 15:13:57

标签: c# .net random generator

我需要你帮助解决一个小问题。我有四个标签,我想在它们上面显示0到100之间的随机值,它们的总和必须是100。

这是我的代码:

private void randomly_Click(object sender, EventArgs e)
{
    double alpha = 0, beta = 0, gamma = 0, delta = 0;
    double temp;
    int tempDouble;

    Random rnd = new Random();

    alpha = rnd.Next(0, 100);

    temp = 100 - alpha;
    tempDouble = (int)temp;
    beta = rnd.Next(0, tempDouble);

    temp = 100 - (alpha + beta);
    tempDouble = (int)temp;
    gamma = rnd.Next(0, tempDouble);

    temp = 100 - (alpha + beta + gamma);
    tempDouble = (int)temp;
    delta = rnd.Next(0, tempDouble);

    temp = alpha + beta + delta + gamma;
    temp = 100 - temp;
    temp = temp / 4;

    alpha = alpha + temp;
    beta = beta + temp;
    gamma = gamma + temp;
    delta = delta + temp;

    cInsertion.Text = alpha.ToString();
    cMoyens.Text = beta.ToString();
    cInternational.Text = gamma.ToString();
    cRecherche.Text = delta.ToString();
}   

问题在于我给alpha提供biggest值的机会,以及delta lowest值。

有没有办法让他们有同样的机会获得真正的random值?

6 个答案:

答案 0 :(得分:45)

你可以这样做:

double alpha = 0, beta = 0, gamma = 0, delta = 0, k = 0;
Random rnd = new Random();

alpha = rnd.Next(0, 100);
beta = rnd.Next(0, 100);
gamma = rnd.Next(0, 100);
delta = rnd.Next(0, 100);

k = (alpha + beta + gamma + delta) / 100;

alpha /= k;
beta /= k;
gamma /= k;
delta /= k;

cInsertion.Text = alpha.ToString();
cMoyens.Text = beta.ToString();
cInternational.Text = gamma.ToString();
cRecherche.Text = delta.ToString();

这样你就说让我们为所有4个变量取一个随机值,然后我们将它们缩放k因子,使它们的总和为100。

答案 1 :(得分:6)

如果您将所有四个值都放在数组then shuffle them中,然后根据它们的序数位置分配它们,该怎么办?这样每个变量(gamma,theta等)具有相同的获得高数字和低数字的概率。

答案 2 :(得分:0)

这是一个非常有趣的问题。我喜欢@Ivan_Ferić的解决方案,我认为,它很完美,但我有另一个想法:

int total = 100;
Random rand = new Random();

int half = rand.next(0,total);   // the line

a = rand.Next(0,half);
b = max - a;
c = rand.Next(0,half);
d = max - c;

(未经测试,可能必须在某些变量中添加+/- 1。)此外,您可以随机播放值。

有趣的部分即将到来。如果我们改变“线”:

min = <some_value>
max = <another_value>;
int half = rand.next(min,max);

...然后我们可以微调结果:

  • min = 0; max = 100:original;
  • min = 20; max = 80:避免小数字;
  • min = 33; max = 100:强制两个数字小于32。

答案 3 :(得分:0)

不是随机生成单个数字,而是生成部分和,然后计算部分:

double alpha, beta, gama, delta = 0;

var rnd = new System.Random();
var cuts = new List<double>();

cuts.Add(Math.Floor(rnd.Next(0, 101)));
cuts.Add(Math.Floor(rnd.Next(0, 101)));
cuts.Add(Math.Floor(rnd.Next(0, 101)));

cuts.Sort();

alpha = cuts[0];
beta = cuts[1] - cuts[0];
gamma = cuts[2] - cuts[1];
delta = 100 - cuts[2];

答案 4 :(得分:0)

如果您想要的数字代表互斥结果的概率,您可以将它们想象为多项分布。由于您需要一个随机概率向量,您应该从多项分布的共轭先验中对其进行抽样:Dirichlet分布。

在代码中,你只是Ivan所建议的,除了alpha,beta,gamma和delta都应该从Gamma分布中绘制,其中形状参数alpha_shape,beta_shape,gamma_shape和delta_shape各自相同。 (让Gamma分布的其他参数为1.)这些形状参数控制预期的相对比例。

答案 5 :(得分:-2)

真实随机数?简而言之,没有。只有一个伪随机数。

<击>

随机数发生器在时钟周期内运行,通常会看到重复的序列。使用的种子取决于当前DateTime.Now的.Tick属性(如果我没记错的话, )。 .Net有很多不错的随机数生成器和API。如果您觉得自己没有时间或者想要自己动手,我会建议您搜索这些。

向上移动评论,因为它似乎更合适。