user3102815
user3102815

Reputation: 71

Weighted Random Number Generator in Javascript

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

Answers (2)

chiliNUT
chiliNUT

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

cwharris
cwharris

Reputation: 18125

First Solution

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.

  • When n = 1 : y === x
  • When n > 1 : y <= x
  • When 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;

y = x^2

Other Functions

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

Related Questions