Javascript\'s MATH object has a random method that returns from the set [0,1) 0 inclusive, 1 exclusive. Is there a way to return a truly random method that includes 1.
This should work properly.
function random_inclusive () {
while (true) {
var value = Math.random() + (Math.random() < 0.5? 0: 1);
if (value <= 1) {
return value;
}
}
}
What we do here is generate additional single random bit to expand PRNG range to [0, 2). Then we simply discard values in (1, 2) and retry until our value hits in [0, 1].
Notice that this method calls Math.random() 4 times on average.
Alternatively, we can speed up things twice by the cost of 1 bit of precision:
var value = Math.random() * 2;
For those who want to test, here is the way. Just assume that Math.random() only has 1 bit of precision and generates either 0 or 0.5. So on the output we should have uniform distribution among values 0, 0.5, and 1.
function random_inclusive_test (samples) {
var hits = {};
for (var i=0; i<samples; i++) {
while (true) {
var value =
(Math.random() < 0.5? 0: 0.5) +
(Math.random() < 0.5? 0: 1);
if (value <= 1) {
break;
}
}
if (!hits[value]) {
hits[value] = 1;
}
else {
hits[value]++;
}
}
console.log(hits);
}
random_inclusive_test(300000);
The solution I found was to use trigonometric equations.
Because sine oscillates from Math.sin(0) = 0 and Math.sin(90) = 1. This repeats until 360 degrees which is equal to 0. However, 360 is still not highly precise so use radians which is 2 * Math.PI. You only need to take the absolute value to get rid of the negative values.
So,
double angle = 2 * Math.PI * Math.random()
double inclusive = Math.abs(Math.sin(angle)) // Math.cos(angle) also works.
You want it to include 1?
return 1 - Math.random();
However, I think this is one of those questions which hints at other problems. Why do you need to include 1? There's probably a better way to do it.