【问题标题】:How to write a random multiplier selection function?如何编写随机乘数选择函数?
【发布时间】:2021-11-16 17:25:37
【问题描述】:

我正在尝试编写一个函数,该函数返回随机选择的以下乘数之一,但遵循频率要求。下表定义的是,对于此函数的 100 万次调用,1500 将返回一次,500 将返回两次,依此类推。

|---------------------|------------------------------|
|      Multiplier     |     Frequency Per Million    |
|---------------------|------------------------------|
|          1500       |         1                    |
|---------------------|------------------------------|
|          500        |         2                    |
|---------------------|------------------------------|
|          200        |         50                   |
|---------------------|------------------------------|
|          50         |         100                  |
|---------------------|------------------------------|
|          25         |         20,000               |
|---------------------|------------------------------|
|          5          |         75,000               |
|---------------------|------------------------------|
|          3          |         414,326              |
|---------------------|------------------------------|
|          2          |         490521               |
|---------------------|------------------------------|

想知道实现这一点的最佳方法是什么。

【问题讨论】:

  • 这些数字是概率还是频率?例如,是否要求每 1,000,000 次调用,1500 乘数将仅返回一次?

标签: c# random


【解决方案1】:

首先,让我们声明模型:

 static Dictionary<int, int> multipliers = new Dictionary<int, int>() {
   {1500,       1},
   { 500,       2},
   { 200,      50},
   {  50,     100},
   {  25,  20_000},
   {   5,  75_000},
   {   3, 414_326},
   {   2, 490_521}, 
 };

然后你就可以轻松选择随机乘数了:

 // Easiest, but not thread safe
 static Random random = new Random();

 ...

 private static int RandomMultiplier() {
   int r = random.Next(multipliers.Values.Sum());

   s = 0;

   foreach (var pair in multipliers.OrderByDescending(p => p.Key)) 
     if (r < (s += pair.Value)) 
       return pair.Key;

   throw new InvalidOperationException($"{r} must not reach this line");
}   
        
...

int multiplier = RandomMultiplier();

【讨论】:

  • 也许SortedList&lt;int, int&gt; 比每次都必须排序的Dictionary&lt;int, int&gt; 更重要。
  • @Theodor Zoulias:如果我们想要生成随机的multiplier,那你是完全正确的。如果我们想要更多,例如如果我们想要某个地方的频率(我们多久给出一次乘数),字典会显得更方便。在所有情况下,集合都很短,可以轻松分类/扫描。
【解决方案2】:

如果设置了需要返回的频率和值,那么就不需要复杂了。您只需要通过添加先前数字的频率来调整 if 块中正在处理的先前数字。

private int GetRandomMultiplier()
{
  var random = new Random();
  var next = random.Next(1000000);
  if (next < 1)
  {
      return 1500;
  }
  else if (next < 3)
  {
      return 500;
  }
  else if (next < 53)
  {
      return 200;
  }
  else if (next < 153)
  {
      return 50;
  }
  else if (next < 20153)
  {
      return 25;
  }
  else if (next < 95153)
  {
      return 5;
  }
  else if (next < 509479)
  {
      return 3;
  }

  return 2;
}

您不想每次都创建一个新的Random,所以创建一个并使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-27
    • 2016-05-02
    • 1970-01-01
    • 2020-07-24
    • 2012-10-07
    • 1970-01-01
    相关资源
    最近更新 更多