Different probability for ranges of random numbers
I'm lo开发者_如何学JAVAoking for the best way of implementing random number generator, that will allow me to have control over probability from what range the generated number will be returned. To visualize what I'm trying to achieve I have a picture :
So to summarize : Let's say that my range is 400. At the beginning I'd like to have 5% probability of getting number 0-20. But at some moment in time I'd like to have this probability increased up to 50%. Hope you get the idea.
Hmm, working on your original I had a pretty simple algorithm to generate ranges in an array in the appropriate proportion, then randomly select a range and generate a random number within that range. No doubt it can be optimised if necessary, but it works for me.
It looks like a lot of code, but 3/4 of it is comments, test data and function, the actual randomRange function is only 17 lines of code.
<script type="text/javascript">
function randomRange(dataArray) {
// Helper function
function getRandomInRange(s, f) {
return (Math.random() * (f-s+1) | 0) + s
}
// Generate new data array based on probability
var i, j = dataArray.length;
var oArray = [];
var o;
while (j--) {
o = dataArray[j];
// Make sure probability is an integer
for (i=0, iLen=o.probability|0; i<iLen; i++) {
oArray.push([o.rangeStart, o.rangeEnd]);
}
}
// Randomly select a range from new data array and
// generate a random number in that range
var oEnd = oArray.length;
var range = oArray[getRandomInRange(0, oArray.length - 1)];
return getRandomInRange(range[0], range[1]);
}
// Test data set. Probability just has to be
// representative, so 50/50 === 1/1
var dataArray = [
{
rangeStart: 0,
rangeEnd : 20,
probability: 1
},
{
rangeStart: 21,
rangeEnd : 400,
probability: 1
}
];
// Test function to show range and number is randomly
// selected for given probability
function testIt() {
var el0 = document.getElementById('div0');
var el1 = document.getElementById('div1');
function run() {
var n = randomRange(dataArray);
if (n <= 20) {
el0.innerHTML += '*';
} else {
el1.innerHTML += '*';
}
}
setInterval(run, 500);
}
</script>
<button onclick="testIt();">Generate random number</button>
<div>Numbers 0 - 20</div>
<div id="div0"></div>
<div>Numbers 21 - 400</div>
<div id="div1"></div>
It sounds to me like what you're looking for is a way to generate numbers on a normal (or Gaussian) distribution (take a look at the Wikipedia page if you don't know what that means).
The Box-Muller transformation can be used to generate pairs of normally distributed numbers.
Here is a c++ implementation of the polar form of the Box-Muller transformation that shouldn't be hard to translate to javascript.
// Return a real number from a normal (Gaussian) distribution with given
// mean and standard deviation by polar form of Box-Muller transformation
double x, y, r;
do
{
x = 2.0 * rand() - 1.0;
y = 2.0 * rand() - 1.0;
r = x * x + y * y;
}
while ( r >= 1.0 || r == 0.0 );
double s = sqrt( -2.0 * log(r) / r );
return mean + x * s * stddev;
Where mean is the mean of the normal distribution and stddev is the Standard Deviation of the distribution. This code is from a MersesenneTwister C++ class that I've been using recently that you can find on Rick Wagner's page. You can find some more useful information about the Box-Muller transformation on this page.
精彩评论