Reputation: 9478
I was asked this question in a interview, so I don't want the solution, just the guidance regarding how to approach it.
You have been given two numbers low and high. And a random generator which generates 0 and 1. I have to generate a number between low and high using that function.
I can get difference between the two numbers and somehow try to generate a number using bit manipulation. But I am not able to figure out how to do that?
Upvotes: 2
Views: 243
Reputation: 12324
Here's a basic bit-by-bit comparison algorithm that gives a random number between low and high, using a random-bit function:
high
by 1 and increase low
by 1 (in case the random bits introduced later all equal those in high
or low
).high_dec
and low_inc
to store whether at least one 1 in high
has been changed into 0, and at least one 0 in low
has been changed into 1, and set both of them to false (these will help avoid the result going out of range).Compare high
and low
bit-by-bit from MSB to LSB with these cases:
high:1
and low:1
then store a 1 if low_inc=false
or store a random bit otherwise (and update high_dec
as necessary).high:1
and low:0
then store a random bit (and update high_dec
or low_inc
as necessary).high:0
and low:1
then store a 0 if high_dec=false
or store a 1 if low_inc=false
or store a random bit otherwise.high:0
and low:0
then store a 0 if high_dec=false
or store a random bit otherwise (and update low_inc
as necessary).Note that the distribution of the random numbers is only uniform if the lowest possible result is a power of 2, and the range is a power of 2. In all cases the whole range is used, but there may be an emphasis on values near the beginning or end of the range.
function between(a, b) {
var lo = (a + 1).toString(2).split(''), // conversion to bit array because
hi = (b - 1).toString(2).split(''), // there is no bit manipulation in JS
lc = false, // low changed
hc = false, // high changed
result = [];
while (lo.length < hi.length) lo.unshift(0); // add leading zeros to low
for (var i = 0; i < hi.length; i++) { // iterate over bits, msb to lsb
var bit = Math.round(Math.random()); // random bit generator
if (hi[i] == 1) {
if (lo[i] == 1) { // case hi:1 lo:1
if (lc == false) bit = 1
else if (bit == 0) hc = true;
} else { // case hi:1 lo:0
if (bit == 0) hc = true
else lc = true;
}
} else {
if (lo[i] == 1) { // case hi:0 lo:1
if (hc == false) bit = 0
else if (lc == false) bit = 1;
} else { // case hi:0 lo:0
if (hc == false) bit = 0
else if (bit == 1) lc = true;
}
}
result.push(bit);
}
return parseInt(result.join(''), 2); // convert bit array to integer
}
document.write(between(999999, 1000100) + "<BR>");
Upvotes: 1
Reputation: 53839
You can do:
range = high - low
n
such that 2^n-1 < range <= 2^n
010011010
(= 154 in decimal)low
to get your final number!Upvotes: 2