4

I am trying to write a random number generator function in C# that would take a minimum, maximum, and weight parameters.

With weight == 0, the result would equal minimum, and with weight == 1, the result would equal maximum. With weight == 0.5, all the numbers within the range would have equal chance of being selected.

What I want to achieve is as the weight is approaching the minimum, the minimum has more chances of being selected and the maximum less, and vice versa.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
tau-badger
  • 75
  • 5
  • 2
    @Plutonix There are different distributions to regard. You seem to only consider the uniform distribution. – Konrad Viltersten Jul 29 '16 at 22:06
  • 2
    There are different ways to approach it. Could you give a few more examples on how the function is supposed to behave for weights like 0.1, 0.25, 0.66 etc.? – Konrad Viltersten Jul 29 '16 at 22:07
  • I'm having trouble deciding what exact values the other weights produce. For instance, if the weight were 0.1, the probability for minimum would be 90%, the maximum 10%, and the values in between would be assigned accordingly. However, I am not sure if the sum of all probabilities should be more than a 100%, as it would be in that case. – tau-badger Jul 29 '16 at 22:17
  • 1
    @tau-badger SO is more about specific coding problems, other stackexchange sites may help more..... Maybe http://programmers.stackexchange.com/ – Eser Jul 29 '16 at 22:18
  • This question is far too broad. You have not provided any information as to what you've already tried, never mind a good [mcve] that shows this, nor any sort of precise specification that explains the type of random numbers you want to return nor _exactly_ how the weight will affect the distribution of the output. There are already a number of Q&A on Stack Overflow showing how to do weighted random selected (e.g. https://stackoverflow.com/questions/56692/random-weighted-choice); maybe those will address your question, or maybe they won't. There are too many ways to interpret this question. – Peter Duniho Jul 29 '16 at 22:29
  • 2
    @tau-badger I'm afraid that is a specification that you will need to provide. Otherwise, there are infinitely many ways to design the method. Statistically speaking, the sum of all the possible outcomes' probabilities **must** be 100%. Are min/max the only values to be produced or do you need **any** number between min and max to be possible? – Konrad Viltersten Jul 29 '16 at 22:29
  • I see now I've posted the question without a solid enough grasp of the problem itself, but some of the answers here are pointing me in the right direction. @KonradViltersten I need any number between the extremes, including the extremes. – tau-badger Jul 29 '16 at 22:39
  • 1
    @tau-badger In such case, you are looking for a *continuous distribution function* and hance, the probability of the max/min can not be 10% and 90%. It is kind of a math stat issue on university level, so I am glad that you are realizing the graspiness needed. :) – Konrad Viltersten Jul 29 '16 at 22:41
  • @KonradViltersten Oh. That is problematic as I evidently don't have a solid enough math background to even understand the difficulty involved with such problems. Thank you, Konrad. You saved me a lot of trouble. – tau-badger Jul 29 '16 at 22:55

3 Answers3

15

I have a short tutorial describing how to do that here:

https://ericlippert.com/2012/02/21/generating-random-non-uniform-data/

Summary:

  • State the function parameterized by your weighting parameter that gives the probability distribution function.
  • Use calculus to integrate that function to get the cumulative distribution function.
  • Invert that function to get the quantile function.
  • Implement the quantile function, and pass the output of a uniformly distributed random source into the quantile function. The result will be a random source that conforms to the desired distribution.
  • Transform that function onto your integer range, and round appropriately.
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
0

This is one from infinite number of possibilities to get weighted values from [0, 1]:

Random rnd = new Random();
double weight = ...; // must be in [0, 1];

double r = rnd.NextDouble();
if (weight < 0.5)
    val = 1 - Math.Pow(r, weight * 2);
else
    val = Math.Pow(r, (1 - weight) * 2);

It can be mapped to [min, max] as

double val2 = val * (max - min) + min;
AlexD
  • 32,156
  • 3
  • 71
  • 65
0

My suggestion is use the Beta distribution, finding functions of your weight which lead to the desired behavior.

For example, assume that the support is between 0 and 1, and that the weight $w$ is also between 0 and 1. The Beta has two parameters, $\alpha$ and $\beta$. Let $\alpha=2*w$ and $\beta=-wlog_2(w)-(1-w)*log_2(1-2)$ (which happens to be the binary entropy function. Then the Beta is degenerate for weights 0 and 1, a standard uniform for a weight of 0.5, and gives valid continuous distributions for other weight values. This particular re-parametrization of the Beta may not be exactly what you want but you could play around with similar functions.

homer
  • 238
  • 3
  • 9