C# 创建一个方法以返回一系列随机值
考虑以下代码。基本思想是返回一个由20个数字组成的逗号分隔列表,其中任何一个数字都可以是介于0和允许的最大值之间的值。每次通过循环时,列表中下一个值所允许的潜在最大值都会减少最后一个随机值 所以它起作用了。。。但这很糟糕。问题是它总是会产生这样的输出: “22,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0” “17,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0” “23,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0” 如何对其进行修改以允许在整个范围内更均匀地分布值C# 创建一个方法以返回一系列随机值,c#,random,range,C#,Random,Range,考虑以下代码。基本思想是返回一个由20个数字组成的逗号分隔列表,其中任何一个数字都可以是介于0和允许的最大值之间的值。每次通过循环时,列表中下一个值所允许的潜在最大值都会减少最后一个随机值 所以它起作用了。。。但这很糟糕。问题是它总是会产生这样的输出: “22,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0” “17,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0” “23,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
public static string RandomRangeOfValuesMaker(int total)
{
var remainingTotal = total + 1;
const int numberOfValues = 20;
var rand = new Random();
var builder = new StringBuilder();
for (var i = 1; i < numberOfValues + 1; i++)
{
var currentRandomNumber = rand.Next(remainingTotal);
remainingTotal = remainingTotal - currentRandomNumber;
builder.Append(currentRandomNumber + ",");
}
var rangeOfValues = builder.ToString().Remove(builder.ToString().Length - 1);
return rangeOfValues;
}
public静态字符串RandomRangeOfValuesMaker(整数合计)
{
var剩余总额=总额+1;
常数int numberOfValues=20;
var rand=new Random();
var builder=新的StringBuilder();
对于(变量i=1;i
更新:我误解了这个问题上声明不好的约束条件;我最初的答案解决了“按降序生成小于m的n个随机数”的问题。原始答案附在下面
实际问题是“将数字m随机划分为n个部分”
有很多方法可以做到这一点。这里有一个;时间是O(m),空间是O(n)。你能改进一下吗
static Random random = new Random();
static IEnumerable<int> Partition(int number, int parts) {
int[] partition = new int[parts];
for(int i = 0; i < number; ++i)
partition[random.Next(parts)] += 1;
return partition;
}
使用下面的助手函数
在这个解决方案和Kyle的解决方案中需要注意的关键不是生成分区的算法——正如我所说,有很多方法可以做到这一点。相反,关键是不要试图在一个函数中做太多的事情。当您试图确保sum属性、单调性和逗号分隔都在同一个位置时,出现了错误。排序20个数字很便宜;把问题外包出去。用逗号分隔一堆东西很便宜;把这个问题也外包出去。编写每个都能很好地完成一件事情的小函数,然后将它们组合成更大的函数
如何对其进行修改以允许在整个范围内更均匀地分布值
public static string RandomRangeOfValuesMaker(int total)
{
var remainingTotal = total + 1;
const int numberOfValues = 20;
var rand = new Random();
var builder = new StringBuilder();
for (var i = 1; i < numberOfValues + 1; i++)
{
var currentRandomNumber = rand.Next(remainingTotal);
remainingTotal = remainingTotal - currentRandomNumber;
builder.Append(currentRandomNumber + ",");
}
var rangeOfValues = builder.ToString().Remove(builder.ToString().Length - 1);
return rangeOfValues;
}
首先选择数字,然后对其进行排序
让我们把它分解一下。第一:随机数的无限序列:
private static Random random = new Random();
public static IEnumerable<int> RandomNumbers(int max)
{
while(true) yield return random.Next(max);
}
任何时候,当你做一些涉及序列的事情时,比如你自己我可以使用内置的序列操作符来表达我想要的工作流吗?我可以构建自己的序列运算符吗?
例如,我们可以将另一个序列运算符设为一行:
public static string CommaSeparated<T>(this IEnumerable<T> items)
{
return string.Join(",", items);
}
你想要什么?20个随机数,按降序排列,用逗号分隔。那么您的程序应该如何读取应该是20个随机数,按降序排列,用逗号分隔。编写程序,使其看起来像是对它试图解决的问题的描述。这将更容易理解,更容易维护,也更容易看出它的正确性。我将以以下内容作为序言:阅读Eric Lippert的答案-他所说的几乎肯定比我更正确(pssst.。他在大学学习数学,在微软从事C#编译器等工作!) 函数返回的X值和Y之和可以写成:
public static string StringyRandomNumbersThatAddUpToMaxNumber(int sumOfRandomNumbers, int numberOfValuesToReturn)
{
var randomNumbers = RandomNumbersThatAddUpToMaxNumber(new List<int>(), sumOfRandomNumbers, numberOfValuesToReturn);
return string.Join(",", randomNumbers);
}
public static IEnumerable<int> RandomNumbersThatAddUpToMaxNumber(List<int> randomNumbers, int sumOfRandomNumbers, int numberOfValuesToReturn)
{
var randomNumberGenerator = new Random();
while (randomNumbers.Sum() < sumOfRandomNumbers)
{
var ceiling = (randomNumbers.Any() ? randomNumbers.Sum() : sumOfRandomNumbers) / 2;
var newNumber = randomNumberGenerator.Next(ceiling);
if (randomNumbers.Sum() + newNumber <= sumOfRandomNumbers)
{
randomNumbers.Add(newNumber);
}
}
if (numberOfValuesToReturn > randomNumbers.Count())
{
randomNumbers.Remove(randomNumbers.Max());
return RandomNumbersThatAddUpToMaxNumber(randomNumbers, sumOfRandomNumbers, numberOfValuesToReturn);
}
return randomNumbers;
}
公共静态字符串StringyRandomNumbers,其addUptoMaxNumber(int-sumOfRandomNumbers,int-numberOfValuesToReturn)
{
var randomNumbers=RandomNumbersThatAddUpToMaxNumber(新列表(),随机数之和,numberOfValuesToReturn);
返回字符串。Join(“,”随机数);
}
公共静态IEnumerable randomNumbers加上MaxNumber(列出randomNumbers、int-sumof随机数、int-numberOfValuesToReturn)
{
var randomNumberGenerator=新随机数();
while(randomNumbers.Sum()
理论上,它可能永远不会返回或抛出StackOverflowException
,但实际上很可能会返回或抛出
我不以任何方式、形状或形式相信结果数可以被认为是真正随机的(因为它消除了每个递归上的最高值,从而允许它有更多的“工作空间”来找到更多的值,以满足它们加起来等于Y的要求),因此请将此代码与注释一起使用。如果您想要一个随机整数序列,将其相加为特定的和,最简单的方法是首先选择[0,sum]范围内的随机整数序列,对其进行排序,然后返回差分:
public static IEnumerable<int> GetSequenceWithSum( Random rand, int count, int sum )
{
// Get a list of count-1 random numbers in the range [0, sum] in ascending order.
// This partitions the range [0, sum] into count different bins of random size.
var partition = Enumerable.Range( 0, count - 1 )
.Select( _ => rand.Next( 0, sum + 1 ) )
.OrderBy( x => x );
// Yield the size of each partition in the range.
int previous = 0;
foreach( int value in partition )
{
yield return value - previous;
previous = value;
}
yield return sum - previous;
}
公共静态IEnumerable GetSequenceWithSum(随机随机随机数、整数计数、整数和)
{
//以升序获取[0,sum]范围内的count-1随机数列表。
//这会将范围[0,sum]划分为多个随机大小的不同存储箱。
var分区=可枚举。范围(0,计数-1)
.Select(=>rand.Next(0,总和+1))
.OrderBy(x=>x);
//生成范围内每个分区的大小。
int-previous=0;
foreach(分区中的int值)
{
收益率返回值-上一个;
先前=值;
}
收益回报总额-以前;
}
我不能确切地说这会给你带来什么样的分布,但它会给你带来更多
public static string StringyRandomNumbersThatAddUpToMaxNumber(int sumOfRandomNumbers, int numberOfValuesToReturn)
{
var randomNumbers = RandomNumbersThatAddUpToMaxNumber(new List<int>(), sumOfRandomNumbers, numberOfValuesToReturn);
return string.Join(",", randomNumbers);
}
public static IEnumerable<int> RandomNumbersThatAddUpToMaxNumber(List<int> randomNumbers, int sumOfRandomNumbers, int numberOfValuesToReturn)
{
var randomNumberGenerator = new Random();
while (randomNumbers.Sum() < sumOfRandomNumbers)
{
var ceiling = (randomNumbers.Any() ? randomNumbers.Sum() : sumOfRandomNumbers) / 2;
var newNumber = randomNumberGenerator.Next(ceiling);
if (randomNumbers.Sum() + newNumber <= sumOfRandomNumbers)
{
randomNumbers.Add(newNumber);
}
}
if (numberOfValuesToReturn > randomNumbers.Count())
{
randomNumbers.Remove(randomNumbers.Max());
return RandomNumbersThatAddUpToMaxNumber(randomNumbers, sumOfRandomNumbers, numberOfValuesToReturn);
}
return randomNumbers;
}
public static IEnumerable<int> GetSequenceWithSum( Random rand, int count, int sum )
{
// Get a list of count-1 random numbers in the range [0, sum] in ascending order.
// This partitions the range [0, sum] into count different bins of random size.
var partition = Enumerable.Range( 0, count - 1 )
.Select( _ => rand.Next( 0, sum + 1 ) )
.OrderBy( x => x );
// Yield the size of each partition in the range.
int previous = 0;
foreach( int value in partition )
{
yield return value - previous;
previous = value;
}
yield return sum - previous;
}