如何在C#中生成两个固定和的数字之间的随机数字序列?
所以我试图生成一个N个数的序列,其中的和是S 现在,我正在这样做:如何在C#中生成两个固定和的数字之间的随机数字序列?,c#,math,random,numbers,C#,Math,Random,Numbers,所以我试图生成一个N个数的序列,其中的和是S 现在,我正在这样做: float baseamount = (float)(amount / norders) * 0.8f; float secondamount = amount / norders; 然后在这两个数字之间生成N个随机数 但是,这会生成一个相当统一的数字范围,而我希望更随机一些,例如,而不是(sum=200,n=10): 16.92321 17.49378 16.26426 16.03404 16.12497 17.53131
float baseamount = (float)(amount / norders) * 0.8f;
float secondamount = amount / norders;
然后在这两个数字之间生成N个随机数
但是,这会生成一个相当统一的数字范围,而我希望更随机一些,例如,而不是(sum=200,n=10):
16.92321 17.49378 16.26426 16.03404 16.12497 17.53131 18.10094 16.86982 17.0831 16.06921
我更喜欢:
12.345 17.4534 19.3542342 11.345345 18.4325235 14.4353245
最好的方法是什么?生成(n-1)个不大于sum/n的随机数,并跟踪部分和(我们称之为PS)。
那么,您的最后一个数字是(sum-PS)
希望这有帮助
编辑:当然,最后一个数字比之前所有的数字都要大。我将研究这个问题的一个更加数学化的解决方案(或者至少我会尝试)。与此同时,我想到了一个“解决办法”:
(我们把随机序列称为a0,…,an)
rd
(您需要选择k)an-=rd
ai
:ai+=rd/(n-1)
如果我把每件事都做得很好,那么总数就不会改变,你就有了一个更统一的序列。k必须由您根据您希望序列的“一致性”程度来选择。此方法创建的n个值的平均值为
总和/计数
随定义的值而变化。在每个循环中,min
和max
的常量计算可实现最后一个值(在本例中,它实际上是数组的第一个值)不太突出。尽管如此,它仍然不是完美的,特别是当你有一个小的平均值和一个大的方差。但也许这会给你一个开始
public static IEnumerable<double> GetValues(int count, double sum, double variance)
{
var rnd = new Random();
var values = new double[count];
var remainingSum = sum;
for (int i = count-1; i > 0; i--)
{
var min = (int)(remainingSum / (i+1) - variance / 2) * 1000;
var max = (int)(remainingSum / (i+1) + variance / 2) * 1000;
var rndVal = rnd.Next(min, max) / 1000.0;
values[i] = rndVal;
remainingSum -= rndVal;
}
values[0] = remainingSum;
return values;
}
公共静态IEnumerable GetValues(整数计数、双和、双方差)
{
var rnd=新随机数();
var值=新的双[计数];
var剩余金额=总和;
对于(int i=count-1;i>0;i--)
{
var最小值=(整数)(剩余总和/(i+1)-方差/2)*1000;
var max=(int)(剩余总和/(i+1)+方差/2)*1000;
var rndVal=下一个(最小值、最大值)/1000.0;
值[i]=rndVal;
剩余金额-=rndVal;
}
值[0]=剩余和;
返回值;
}
静态随机=新随机();
浮点[]生成(浮点和,整数n,浮点最小限制)
{
浮点最大值=总和-最小极限*n;
浮动[]arr=新浮动[n];
对于(int i=0;i0;i--)
{
arr[i]=arr[i]-arr[i-1]+minLimit;
}
arr[0]+=minLimit;
返回arr;
}
你看过这篇文章了吗?现在看看吧,因为这些数字是相关的,你不能用一些独立的随机变量来解决这个问题。你认识到这是不可能的吗?如果总和=200,n=10,则每个数字的平均值为20。因此,随机抽样将产生一些高于20的数字,一些低于20的数字,以使总和保持在200。根据您的要求,您希望数字明确地以20为单位,因此所有数字都将小于20,并且不可能将总和设置为200。即使在您的示例中,总和也远远超过200,使用多个随机实例也不是一个好主意。如果同时创建它们,则Next()的结果将是相同的。测试:for(inti=0;i<9;i++){Console.WriteLine(new Random().Next());}
static Random random = new Random();
float[] Generate(float sum, int n, float minLimit)
{
float max = sum - minLimit * n;
float[] arr = new float[n];
for (int i = 0; i < n - 1; i++)
{
arr[i] = (float)random.NextDouble() * max;
}
arr[n - 1] = max;
Array.Sort(arr);
for (int i = n - 1; i > 0; i--)
{
arr[i] = arr[i] - arr[i - 1] + minLimit;
}
arr[0] += minLimit;
return arr;
}