如何在1-9之间生成30个随机数,在C#中总共加起来200(或任意N)?
我正在尝试生成一串可以加起来为N的数字.
我不确定这方面的统计数据,但是,这里的问题是你不想随意选择一个数字,这使得无法通过过冲或下冲来将N与M个条目相加.我是这样做的:
static void Main() { int count = 30; int[] numbers = getNumbers(count, 155); for (int index = 0; index < count; index++) { Console.Write(numbers[index]); if ((index + 1) % 10 == 0) Console.WriteLine(""); else if (index != count - 1) Console.Write(","); } Console.ReadKey(); } static int[] getNumbers(int count, int total) { const int LOWERBOUND = 1; const int UPPERBOUND = 9; int[] result = new int[count]; int currentsum = 0; int low, high, calc; if((UPPERBOUND * count) < total || (LOWERBOUND * count) > total || UPPERBOUND < LOWERBOUND) throw new Exception("Not possible."); Random rnd = new Random(); for (int index = 0; index < count; index++) { calc = (total - currentsum) - (UPPERBOUND * (count - 1 - index)); low = calc < LOWERBOUND ? LOWERBOUND : calc; calc = (total - currentsum) - (LOWERBOUND * (count - 1 - index)); high = calc > UPPERBOUND ? UPPERBOUND : calc; result[index] = rnd.Next(low, high + 1); currentsum += result[index]; } // The tail numbers will tend to drift higher or lower so we should shuffle to compensate somewhat. int shuffleCount = rnd.Next(count * 5, count * 10); while (shuffleCount-- > 0) swap(ref result[rnd.Next(0, count)], ref result[rnd.Next(0, count)]); return result; } public static void swap(ref int item1, ref int item2) { int temp = item1; item1 = item2; item2 = temp; }
我没有太多时间来测试这个如此道歉,如果我的逻辑中有一个缺陷.
编辑:
我做了一些测试,一切看起来都很稳固.如果你想要一个漂亮的漂亮的传播,看起来你想要的东西沿着这条线Total = Count * ((UPPER + LOWER) / 2)
.虽然我相当肯定,是身份的区别UPPER
,并LOWER
增加了更灵活的这种变.
问题是我们希望所有数字都限制在1-9 并加起来为N.所以我们必须逐个生成每个数字并确定下一个数字的实际边界.
这当然会在列表末尾产生统计偏差,因此我建议在生成后将数组洗牌一次.
要确定下一个数字的边界,请执行以下操作:上限=取剩余的总和减去(剩余的元素数量*min).下限=取剩余的总和减去(剩余的元素数量*max).
像(未经测试)的东西:
public static ListRandomList(int digitMin, int digitMax, int targetSum, int numDigits) { List ret = new List (numDigits); Random random = new Random(); int localMin, localMax, nextDigit; int remainingSum = targetSum; for(int i=1; i<=numDigits; i++) { localMax = remainingSum - ((numDigits - i) * min); if(localMax > max) localMax = max; localMin = remainingSum - ((length - i) * max); if(localMin > min) localMin = min; nextDigit = random.Next(localMin, localMax); ret.Add(nextDigit); remainingSum -= nextDigit; } return ret; }
这里的想法是在生成数字时,剩余数字的可能值范围变得更小,就像限制函数归零目标总和一样.有点.
编辑:我必须将for循环更改为从1开始,因为我们希望生成此元素后剩余的元素数量.
EDIT2:把它放在一个方法的完整性和改变length
是numDigits
为了便于阅读.