Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建一个方法以返回一系列随机值_C#_Random_Range - Fatal编程技术网

C# 创建一个方法以返回一系列随机值

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

考虑以下代码。基本思想是返回一个由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”

如何对其进行修改以允许在整个范围内更均匀地分布值

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