Biased random number generator

I am looking for a random number generator that may be biased. For example, let's say I want a random number between 1-5, with probability:

1: comes in 20% of cases
2: Comes in 10% of cases
3: Comes in 40% of cases
4: Comes in 25% of cases
5: Comes in 5% of cases

Is there anything in the standard library or in other libraries that could do this? Alternatively, is there an effective way to do this yourself?

+7
c ++ random
source share
10 answers

The Boost random number library provides the ability to specify different shaped distributions for your generator. This is a great library - see http://www.boost.org/doc/libs/1_42_0/libs/random/index.html .

+9
source share

For your problem, just select a random item from this list evenly:

[1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5] 

In general, check this answer: Weighted random numbers


In TR1 and C ++ 0x, there is a <random> header that contains a discrete_distribution class for creating such numbers, among others.

You can also check the GSL, which contains much more random distributions (and random number generators) than the standard <random> library, (But keep in mind that GSL uses GPLv3.)

+16
source share

The best way, perhaps, is simply to take a regular, unbiased random generator, and then return based on the interval over which its value falls.

Just an if statement, which gives 1 for 0: 0.2, 2 for 0.2: 0.3, 3 for 0.3: 0.7, 4 for 0.7: 0.95 and 5 for 0.95: 1. It is best to do either the lower or upper limit of the interval inclusive and other exclusive.

 int biasedRandom(){ double i = randomNumber(); if(i<= 0.2){return 1;} else if(i <= 0.3){return 2;} else if(i <= 0.7){return 3;} else if(i <= 0.95){return 4;} else{return 5;} } 

Something like that.

+12
source share

What you are describing is an implementation of a random number generator that relies on a specific probability distribution. For example, drawing numbers from a Gaussian distribution should draw random numbers so that the probability of a particular draw x is proportional alt text
(source: wikimedia.org )
,

In general, the approach is to extract from the uniform random distribution, and then select the value of the required integral distribution function (CDF) in this rendered place. In the case of normal Gaussian, draw a random number x from the uniform distribution (this is what standard random number generators should give), and then select alt text as a random, Gaussian distributed value. For your case, the CDF you are describing is a step-by-step continuous step function that can be implemented using any of the many (correct) answers that you have already received.

Of course, these are all trifles. What you have to do is use a library that already processes this for you. Statistics and random number generation are not trivial, and there is no need to reinvent the wheel. See Neil's answer (and check out the Boost random number library).

+5
source share

Late party at this one. Here is the C ++ 0x answer:

 #include <iostream> #include <random> #include <iterator> int main() { // Set up distribution double interval[] = {1, 2, 3, 4, 5, 6}; double weights[] = { .2, .1, .4, .25, .05}; std::piecewise_constant_distribution<> dist(std::begin(interval), std::end(interval), std::begin(weights)); // Choose generator std::mt19937 gen; // seed as wanted // Demonstrate by pouring into avg[rand-1] const unsigned N = 1000000; double avg[sizeof(weights) / sizeof(weights[0])] = {0}; for (unsigned i = 0; i < N; ++i) avg[static_cast<unsigned>(dist(gen)) - 1]++; // Comute averages for (double* i = std::begin(avg); i < std::end(avg); ++i) *i /= N; // Display for (unsigned i = 1; i <= sizeof(avg)/sizeof(avg[0]); ++i) std::cout << "avg[" << i << "] = " << avg[i-1] << '\n'; } 

What are the solutions for me:

 avg[1] = 0.199779 avg[2] = 0.100002 avg[3] = 0.400111 avg[4] = 0.250257 avg[5] = 0.049851 
+4
source share

Why don't you just use a regular random number generator that returns a number between 0.0 and 1.0 and wrap it with another function that returns a number according to your requirements?

as

 double biased (double seed) { if (seed >= 0.0 && seed <0.2) return 1; else if ... } 
0
source share

Throw a random real number x into [0,1], if 0< x<0.2 return 1 , if 0.2<x <0.3 return 2 , etc.

See here for a common problem.

0
source share

Kenny gave the appropriate answer that matches your particular frequency distribution.

A more general answer works with CDF - the cumulative distribution function - for data and uses a single random number to select a value in the distribution.

0
source share

I am doing the same thing and I found this: http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/

Seems good enough for the stated purpose.

0
source share
 #include <boost/random/discrete_distribution.hpp> #include <boost/random/mersenne_twister.hpp> #include <boost/random/variate_generator.hpp> #include <iostream> int main() { unsigned int seed = 42; boost::mt19937 generator(seed); // return 0 with probability 10% // 1 40% // 2 50% boost::random::discrete_distribution<int> custom_dist{1,4,5}; boost::variate_generator<boost::mt19937&, boost::random::discrete_distribution<int> > rndn(generator, custom_dist); for (unsigned int i = 0; i<10000; i++) { std::cout << rndn() << std::endl; } return 0; } 

And here is a graph of the result:

Output

0
source share

All Articles