Let's assume you are starting with finding a random floating-point number of uniform distribution 0 to 1. You need to convert it to you non-uniform (weighted) distribution, which is a kind of uniform, with giving each name different range on distribution mapping function. This function is very simple, you will need a simple array storing ranges and names. You will need to search a range in this array.
This is the array definition:
class NameDescriptor {
internal NameDescriptor(string name, double low, double high) {
this.Low = low;
this.High = high;
this.Name = name;
}
internal double Low { get; private set; }
internal double High { get; private set; }
internal string Name { get; private set; }
}
Create an array of this element, by the number of names. To populate the array, re-work recurrently your probability into ranges withing 0..1.
Say, you have percentage values per name 1.5, 3, 2… Then the
Low
and
High
values should be
0 to 0.015 (1.5/100)
0.015 to 0.045 (1.5/100 + 3/100)
0.045 to 0.065 (1.5/100 + 3/100 + 2/100)
...
Now, your uniformly-distributed value 0 to 1 will fall into one of these ranges. Find the instance of
NameDescriptor
in the array by this criterion. I did not devise exact algorithm, bit of course it should not be that slow the linear search. The simplest algorithm would be pretty fast (but not the fastest possible) divide-by-two algorithm. It is fast, because all your ranges are ordered. Roughly speaking, you start with middle array index and check that the value fits in the range. If it does not, determine is the suitable range is on left or on right of your attempted element. This way, you divided your search variant by two. And so on…
When the array element is found, your put its
Name
to output.
—SA