I understand you can generate a random number in JavaScript within a range using this function:
function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Courtesy of Ionuț G. Stan here.
What I want to know is if you can generate a better random number in a range using crypto.getRandomValues() instead of Math.random(). I would like to be able to generate a number between 0 and 10 inclusive, or 0 - 1, or even 10 - 5000 inclusive.
You'll note Math.random() produces a number like: 0.8565239671015732.
The getRandomValues API might return something like:
- 231 with
Uint8Array(1)
- 54328 with
Uint16Array(1)
- 355282741 with
Uint32Array(1)
.
So how to translate that back to a decimal number so I can keep with the same range algorithm above? Or do I need a new algorithm?
Here's the code I tried but it doesn't work too well.
function getRandomInt(min, max) {
// Create byte array and fill with 1 random number
var byteArray = new Uint8Array(1);
window.crypto.getRandomValues(byteArray);
// Convert to decimal
var randomNum = '0.' + byteArray[0].toString();
// Get number in range
randomNum = Math.floor(randomNum * (max - min + 1)) + min;
return randomNum;
}
At the low end (range 0 - 1) it returns more 0's than 1's. What's the best way to do it with getRandomValues()?
Many thanks
The easiest way is probably by rejection sampling (see http://en.wikipedia.org/wiki/Rejection_sampling). For example, assuming that
max - min
is less than 256:IMHO, the easiest way to generate a random number in a
[min..max]
range withwindow.crypto.getRandomValues()
is described here.An ECMAScript 2015-syntax code, in case the link is TL;TR: