如何编写随机乘数选择函数?

How to write a random multiplier selection function?

我正在尝试编写一个函数,returns 以下乘法器之一随机选择但遵循频率要求。下面 table 定义的是,对于此函数的 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               |
|---------------------|------------------------------|

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

如果设置了需要返回的频率和值,就不需要复杂的了。您只需要通过添加先前数字的频率来调整 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,所以创建一次并使用它。

首先,让我们声明模型:

 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();