Advertisement

Choosing a Non-Uniform Random Integer

Started by May 08, 2003 11:14 AM
2 comments, last by redmage30 21 years, 9 months ago
Can somebody out there help me with this problem? Say I have an object which performs some action with some given average of frequency. For example, say you have a swordsman, and you want him to take on average 3.2 hacks to kill an enemy over the course of many, many attacks. Say you are allowed anywhere from 1 to 10 hacks per attack ... 1 hack minimum to kill an enemy, 10 hacks maximum to kill any enemy, and you want to choose from 1-10 randomly to decide how many hacks are used in each attack. However, you don''t want this to be a uniform distrubtion because you want to center the average around 3.2 hacks. Additionally, the average hacks (3.2 in this example) can vary depending on character attributes. Some swordsmen might take on average 3.0 hacks, others 3.5, some 4.0, etc. Does anybody have some ideas for how I can choose this random number (1-10) and still get averages near the appropriate levels for the characters attributes? I''ve thought about using a Gaussian random number generator with the mean at the level I want, but since my overall range (1-10) is not centered around the average I want (in the 3.x range), I don''t think this will work. Another thought I had is to have some sort of feedback where I choose 1-10 with a uniform random generator and monitor the current average to make outcomes more or less likely in future events. But I''m sure there are more elegant solutions out there. Any ideas?
I guess you could use a binomial distribution. Bin(9, 0.266) + 1 should give you integers 1 to 10 with mean 3.4.
Advertisement

  double random_in_range_with_mean(double a, double b, double mean){   double normalized_mean = (mean-a)/(b-a);   double exp = -1 + 1/normalized_mean;   double r = pow((double)rand()/RAND_MAX,exp);   return a+r*(b-a);}double round_preserving_mean(double x){   double i = floor(x);   double m = x-i;   if(rand()<=RAND_MAX*m)      i+=1;   return i;}int number_you_need = round_preserving_mean(random_in_range_with_mean(1,10,3.2));  


This is generating a uniform distribution, raising the result to some power to distort the mean (like in gamma correction for colours) and scaling the result to fit in the range. If you need your number to be an integer, you can round randomly so that the mean is preserved.
For a quick n'' dirty method: rand() - rand() will give you a triangle-shaped distribution from -RAND_MAX to RAND_MAX, with the mean at 0.


How appropriate. You fight like a cow.

This topic is closed to new replies.

Advertisement