Reputation: 71
I am using the following code to generate a random number:
function getRandomInt (min, max) {
return Math.floor((Math.random() * (max - min + 1)) + min;
}
What I want to do is add a weighting that favours the numbers at the lower end of the range.
I thought about maybe trying to multiply the numbers by 1/cosine.
Would this work and does anyone know how I might go about it?
Many thanks!
Upvotes: 2
Views: 4415
Reputation: 19573
EDIT: there was a type in the final formula, log(2+log(x)) is incorrect it should have been log(1+log(x))+1, its fixed now.
If you are using logarithmic weighting, using something like
var x = Math.random();
var weighted = x * Math.log(1+x);
would make 0.5 weigh in at around 0.2, but 1 would only weigh in at around 0.69.
Using this
var x = Math.random();
var weighted = x * Math.log(2 + Math.log(x));
would allow 1 to weigh in at 1. So combine them, and this
var x = Math.random();
var weighted = (x <= 0.5) ? x * Math.log(1 + x) : x * Math.log(1 + Math.log(x))+1;
should do the trick
Upvotes: 2
Reputation: 18125
You need a function which contains the points (0, 0) and (1, 1). For instance: x^n
when n > 0
Math.pow(1, n) === 1
And
Math.pow(0, n) === 0
Therefore, you would just change n
depending on how you want the weighting to work.
n = 1
: y === x
n > 1
: y <= x
0 < n < 1
: y >= x
So, if you want lower values to be favored over higher values, simply use n > 1
.
var weighted = Math.pow(Math.random(), 2);
Then you can scale the result as usual.
var scaled = Math.floor(weighted * (max - min + 1)) + min;
Likewise, you could use any continuous function which contains the points (0, 0), (1, 1), and has range and domain of [0, 1].
Sine
y = sin(xπ/2)
Cosine
y = 1 - cos(xπ/2)
Upvotes: 12