【问题标题】:Generate 30 Random Numbers from a given sum从给定的总和生成 30 个随机数
【发布时间】:2013-06-12 03:23:15
【问题描述】:

我正在用 C# 编写一份报告,其中给了我一个部门打印的总数量,我必须根据 3 月 1 日打印出 10 份论文的月份日期分发它们,依此类推到 3 月 31 日.

我有一个表格,用于计算总打印输出数。 我有一个月份选择器。

从月份我得到总天数,这是要生成的总数,例如:30 或 31 或 28

场景:

2000 年 3 月打印输出 月总和:2000 要生成的数字:31

这是我的代码

        int sum = 2345;
        int nums = 23;
        Random rand = new Random();
        int newNum = 0;
        int[] ar = new int[23];
        for (int i = 0; i < nums; i++)
        {
            newNum = rand.Next(0, sum);
            ar[i] = newNum;
            sum = sum - newNum;
        }
        for (int i = 0; i < 23 ; i++)
        {
            Console.WriteLine(ar[i]);

        }
        Console.ReadLine();

发生的事情是在结尾数字中它变为零。我希望像一个索引一样正态分布,它首先存储最大值,最后减小。

我们安装了第三方理光打印/复印机,第三方向我们收取一定的费用,他们计算出我们部门已经打印了 3000 份打印件,所以我们必须在几天内随机分发它们,打印出报告并获得我们部门负责人的付款发票。

部门的人在 Excel 上做这件事,我提供给他们一个解决方案。 Windows 窗体应用程序已构建,我只需要输入此逻辑即可。 感谢您的反馈

【问题讨论】:

标签: c# .net random


【解决方案1】:

您可以使用分区轻松做到这一点。对于产生 10 件事情的 4 天月:生成 3 个介于 0 和 10(含)之间的随机数。对它们进行排序并将 10 附加到数字列表中。所以我们也许有:

3 6 6 10

哪些分区我们的打印:

p p p | p p p | | p p p p

【讨论】:

  • 是的,这是正确的做法。代码here.
  • 我不太确定这是统一的。我在理论上没有考虑太多,但只是凭经验在 R 中进行并查看直方图,它看起来严重偏向于小数字,例如hist(diff(排序(c(0,sample(10000,200,replace=T),10000))))。另一方面,我看不出它是如何统一和加起来的。我需要更多地从理论上考虑。
【解决方案2】:

如果你想得到 23 个随机数,总和为 2345,你可以使用这个代码:

        int sum = 2345;
        int nums = 23;
        int max = sum / nums;
        Random rand = new Random();
        int newNum = 0;
        int[] ar = new int[23];
        for (int i = 0; i < nums-1; i++) {
            newNum = rand.Next(max);
            ar[i] = newNum;
            sum-= newNum;
            max = sum / (nums-i-1);
        }
        ar[nums - 1] = sum;

它会给你:

【讨论】:

  • 从数学上讲,这不是均匀分布的。
  • 你并没有真正改变它的作用。算法本身是有缺陷的。或者也许规格是。我不确定。你会得到很多零,或者结果小于 30。不确定根据 OP 是否有效。
  • int sum = 2345;整数 = 23;随机 rand = new Random(); int newNum = 0; int[] ar = 新的 int[23]; for (int i = 0; i
  • int sum = 2345;整数 = 23;随机 rand = new Random(); int newNum = 0; int[] ar = 新的 int[23]; for (int i = 0; i
  • 他所说的“取决于先前的随机”的意思是“与先前的结果相关”,这非常不随机。阅读一些基础知识here
【解决方案3】:

这是我生成 30 个具有特定总和的随机数的想法:

int sum = 3000;
int size = 30; // assumes that (sum % size == 0)
int[] result = new int[size];
Random rand = new Random();
int x = sum / size;

for (int i = 0; i < size; i++)
{
    result[i] = x;
}

for (int i = 0; i < x; i++)
{
    var a = rand.Next(size - 1); // not sure if parameter is inclusive?
    var b = rand.Next(size - 1); // should return number between 0 and size-1 inclusively

    result[a]++;
    result[b]--;
}

int testSum = result.Sum(); // will equal "sum" (3000)

不过,Lee Daniel Crocker 链接到 this,我认为这是一个更好的解决方案。非常简洁直观。

【讨论】:

  • 这行得通,但不会是统一的。正确的算法是here
  • @LeeDanielCrocker 我同意。这是一个漂亮的解决方案。但我不确定我的不统一......你能解释一下为什么会这样吗?
  • 显而易见的是,您的方法永远不会产生超出范围 [70, 130] 的任何值。
  • @LeeDanielCrocker 错了。我将所有数字初始化为 100 并运行循环 100 次。单个值可以是0200,但我确实明白你的意思。你说的对。我会留下答案,以免丢掉代码;)
  • 我想您可能打算使用x 作为兰特限制,而不是size
猜你喜欢
  • 1970-01-01
  • 2011-09-18
  • 2012-10-17
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 2011-04-05
  • 2013-05-28
相关资源
最近更新 更多