2011-04-30 76 views
23

我需要你的帮助,有点问题。我有四个标签,我想显示到100 0它们之间的随机值,并把它们的总和必须是100如何生成总和为预定值的N个随机值?

这是我的代码:

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值?

+0

A **真**随机数?总之,没有。只有一个伪随机数。 随机数发生器运行时钟周期,通常会看到重复的序列。使用的种子取决于当前DateTime.Now的.Tick属性(*如果我没有记错*)。有许多像样的随机数字生成器和API。我会建议寻找那些,如果你觉得你没有时间或想要推出自己的。 – IAbstract 2011-04-30 16:00:43

回答

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.

+5

+1非常聪明。 – Puddingfox 2011-04-30 15:47:02

+2

+1清晰且简单... – 2011-04-30 16:33:19

-2

A real random number?总之,没有。只有一个伪随机数。

随机数发生器运行时钟周期,通常会看到重复序列。使用的种子取决于当前DateTime.Now的.Tick属性(如果我没记错的话 。有许多像样的随机数字生成器和API。我会建议寻找那些,如果你觉得你没有时间或想要推出自己的。

上传到评论,因为它似乎更合适。

+0

与我的代码,你可以说这是一个随机数字。 – 2011-04-30 15:19:14

+0

...标准P-RNG的问题在于,由于时钟的循环特性,它将执行时几乎没有偏差。 – IAbstract 2011-04-30 15:22:32

+0

-1。你对PRNGs的评价是真实的,但是是不合理的 – finnw 2011-04-30 15:53:59

6

如果将所有四个值都粘贴在一个数组中,then shuffle them,然后根据它们的序数位置来分配它们会怎么样?这样,每个变量(伽玛,θ等)具有相等的可能性,从而获得高与低的数字。

+2

+1你是唯一真正阅读这个问题的人吗? ;) – Guffa 2011-04-30 15:27:21

+1

这给了所有四个值相同的分布,但它是一个非常奇怪的分布。 – 2011-04-30 16:16:32

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

...那么我们就可以微调结果:

  • 分钟= 0;最大= 100:原始;
  • min = 20;最大= 80:避免小数字;
  • min = 33;最大值= 100:强制两个数字小于32。
+0

即使min = 0,max = 100,这与Ivan的解决方案并不相同,因为如果半数<5,即发生5%的时间,那么两个数字将和小于5.为了在Ivan的解决方案中发生这种情况,两个数字必须小于5,而两个数字大于50,这只会发生在3/8%的时间。 – 2011-04-30 17:48:35

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

+1为什么这甚至是低调?事实上,这是一个很好的解决方案,不必依赖于分割/乘法。 – 2012-06-26 13:45:30

+1

谢谢@Philip。通常情况下,人们会希望在研究生阶段的概率和统计类别中学到的技巧可以与现成的解决方案相媲美,但我认为天真的选民更喜欢他们自己提出的天真解决方案。 – 2012-06-26 14:09:46

+0

我会非常怀疑阿尔法和三角洲有相同的分布作为测试版和伽马,不像伊万的。 – gnasher729 2014-03-30 17:05:47

0

如果你想代表互相排斥的结果概率的数字,你可以把它们想象为多项分布。既然你想要一个随机的概率向量,你应该在多项分布之前从共轭中抽样:Dirichlet分布。

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