简体   繁体   中英

How to write a random multiplier selection function?

I am trying to write a function that the returns one of the following multipliers randomly selected but following the frequency requirement. What below table defines is that for 1 Million calls to this function the 1500 will be returned once, 500 twice and so on.

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

Wondering what would be the best way to approach implementing this.

If the frequency and value that needs to be returned are set, then nothing complicated is needed. You just need to adjust for the previous numbers being handled in the if blocks by adding the frequency of the previous numbers.

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

You don't want to create a new Random every time though, so create one once and use that.

First, let's declare the model:

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

Then you can easily choose random multiplier:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM