如何生成 N 个随机值,其总和等于预定值?

发布于 2024-11-04 14:39:12 字数 1074 浏览 3 评论 0原文

我需要你的帮助来解决一个小问题。我有四个标签,我想在它们上显示 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 有机会获得 最大值,对于增量来说是最低值。

有什么方法可以让他们有相同的机会获得真正的随机值吗?

I need your help with a little problem. I have four labels and I want to display on them random value between 0 to 100, and the sum of them must be 100.

This is my code :

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();
}   

The problem is that I'm giving to the alpha the chance to have the biggest value, and for delta the lowest value.

Is there any way to give them all the same chance to have a real random value?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

谢绝鈎搭 2024-11-11 14:39:12

你可以这样做:

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。

You could do something like this:

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();

This way you're saying let's take a random value for all 4 variables, and then we'll scale them by a factor k that'll make their sum be 100.

酒废 2024-11-11 14:39:12

What if you stick all four values in an array, then shuffle them, then assign them according to their ordinal position? That way each variable (gamma, theta, etc.) has equal probability of getting a high vs low number.

再浓的妆也掩不了殇 2024-11-11 14:39:12

这是一个非常有趣的问题。我喜欢@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;最大值 = 100:原始;
  • 分钟= 20; max = 80:避免数字太小;
  • 分钟= 33; max = 100:强制两个数字小于 32。

It's a very interesting problem. I like @Ivan_Ferić's solution, I think, it's perfect, but I have another idea:

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;

(Not tested, maybe +/-1 must be added to some of vars.) Also, you may shuffle values.

The interesting part is coming now. If we change "the line":

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

...then we can finetune the result:

  • min = 0; max = 100: original;
  • min = 20; max = 80: avoid little numbers;
  • min = 33; max = 100: force two numbers to be less than 32.
隱形的亼 2024-11-11 14:39:12

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

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];

Instead of generating the individual numbers randomly, generate the partial sums, then calculate the parts:

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];
酷遇一生 2024-11-11 14:39:12

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

在代码中,您按照 Ivan 的建议进行操作,除了 alpha、beta、gamma 和 delta 都应该从 Gamma 分布中绘制,形状参数分别为 alpha_shape、beta_shape、gamma_shape 和 delta_shape。 (令 Gamma 分布的另一个参数为 1。)这些形状参数控制预期的相对比例。

If the numbers that you want represent probabilities of mutually exclusive outcomes, you can imagine them as a multinomial distribution. Since you want a random probability vector, you should sample that from the conjugate prior of the multinomial distribution: the Dirichlet distribution.

In code, you just what Ivan suggested, except that alpha, beta, gamma, and delta should all be drawn from Gamma distributions with shape paramaters alpha_shape, beta_shape, gamma_shape, and delta_shape respective. (Let the other parameter of the Gamma distribution be 1.) These shape parameters control the expected relative proportions.

别想她 2024-11-11 14:39:12

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

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

已移至评论似乎更合适。

A real random number? In short, no. Only a pseudo-random number.

The random number generator operates off clock cycles and it is typical to see repeated sequences. The seed used depends on the .Tick property of the current DateTime.Now (if I remember correctly). There are a lot of decent random number generators and APIs for .Net.I would recommend searching for those if you feel like you don't have the time or desire to put into rolling your own.

Moved up to comments as it seems more appropriate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文