1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <cmath>
using namespace std;
//======================================================================
// Return the upper limits of each partition of random numbers
vector<int> weightToLimit( const vector<double> &weight )
{
int N = weight.size();
// Find cumulative weights
vector<double> sumWeight( N );
for ( int i = 0; i < N; i++ ) sumWeight[i] = ( i ? sumWeight[i-1] : 0 ) + weight[i];
// Split a CONTINUOUS number range -0.5 to RAND_MAX + 0.5, then round DOWN to get upper limits (inc. -1)
vector<int> upperLimit( N );
for ( int i = 0; i < N; i++ ) upperLimit[i] = floor( -0.5 + ( 1.0 + RAND_MAX ) * sumWeight[i] / sumWeight[N-1] );
return upperLimit;
}
//======================================================================
// Return the result of one roll (between 0 and SIDES - 1)
int roll( const vector<int> &upperLimit )
{
int r = rand();
int i = 0;
while ( upperLimit[i] < r ) i++;
return i;
}
//======================================================================
int main()
{
srand( time( 0 ) );
// vector<double> weight = { 1, 1, 1, 1, 1, 1 }; // Unbiased 6-sided die
vector<double> weight = { 0, 0, 1, 1, 2, 2 }; // Very biased die
int SIDES = weight.size();
int NROLLS = 1000000;
vector<int> number( SIDES, 0 );
vector<int> upperLimit = weightToLimit( weight );
for ( int r = 1; r <= NROLLS; r++ ) number[ roll( upperLimit ) ]++;
cout << "Percentages:\n";
for ( int s = 1; s <= SIDES; s++ )
{
cout << s << '\t' << 100.0 * number[s-1] / NROLLS << '\n';
}
}
|