title: Random weighted choice
body: <p>Consider the class below that represents a Broker:</p>
  
  <pre><code>public class Broker
  {
      public string Name = string.Empty;
      public int Weight = 0;
  
      public Broker(string n, int w)
      {
          this.Name = n;
          this.Weight = w;
      }
  }
  </code></pre>
  
  <p>I'd like to randomly select a Broker from an array, taking into account their weights.</p>
  
  <p>What do you think of the code below?</p>
  
  <pre><code>class Program
      {
          private static Random _rnd = new Random();
  
          public static Broker GetBroker(List&lt;Broker&gt; brokers, int totalWeight)
          {
              // totalWeight is the sum of all brokers' weight
  
              int randomNumber = _rnd.Next(0, totalWeight);
  
              Broker selectedBroker = null;
              foreach (Broker broker in brokers)
              {
                  if (randomNumber &lt;= broker.Weight)
                  {
                      selectedBroker = broker;
                      break;
                  }
  
                  randomNumber = randomNumber - broker.Weight;
              }
  
              return selectedBroker;
          }
  
  
          static void Main(string[] args)
          {
              List&lt;Broker&gt; brokers = new List&lt;Broker&gt;();
              brokers.Add(new Broker("A", 10));
              brokers.Add(new Broker("B", 20));
              brokers.Add(new Broker("C", 20));
              brokers.Add(new Broker("D", 10));
  
              // total the weigth
              int totalWeight = 0;
              foreach (Broker broker in brokers)
              {
                  totalWeight += broker.Weight;
              }
  
              while (true)
              {
                  Dictionary&lt;string, int&gt; result = new Dictionary&lt;string, int&gt;();
  
                  Broker selectedBroker = null;
  
                  for (int i = 0; i &lt; 1000; i++)
                  {
                      selectedBroker = GetBroker(brokers, totalWeight);
                      if (selectedBroker != null)
                      {
                          if (result.ContainsKey(selectedBroker.Name))
                          {
                              result[selectedBroker.Name] = result[selectedBroker.Name] + 1;
                          }
                          else
                          {
                              result.Add(selectedBroker.Name, 1);
                          }
                      }
                  }
  
  
                  Console.WriteLine("A\t\t" + result["A"]);
                  Console.WriteLine("B\t\t" + result["B"]);
                  Console.WriteLine("C\t\t" + result["C"]);
                  Console.WriteLine("D\t\t" + result["D"]);
  
                  result.Clear();
                  Console.WriteLine();
                  Console.ReadLine();
              }
          }
      }
  </code></pre>
  
  <p>I'm not so confident. When I run this, Broker A always gets more hits than Broker D, and they have the same weight.</p>
  
  <p>Is there a more accurate algorithm?</p>
  
  <p>Thanks!</p>