I remember reading about the method of efficiently using random bits in an article on a math-oriented website, but I can’t find the right keywords on Google to find it anymore, and that’s not in my browser history.
The essence of the problem that was asked was to take a sequence of random numbers in the domain [ domainStart , domainEnd ) and effectively use the bits of the sequence of random numbers for uniform design in the range [ rangeStart , rangeEnd ). Both the domain and the range are integers (more precisely, long , not Z). What is the algorithm for this?
Implementation, I have a function with this signature:
long doRead(InputStream in, long rangeStart, long rangeEnd);
in based on CSPRNG (served by hardware RNG due to SecureRandom), which I should use; the return value should be between rangeStart and rangeEnd , but the obvious implementation of this is wasteful:
long doRead(InputStream in, long rangeStart, long rangeEnd) { long retVal = 0; long range = rangeEnd - rangeStart;
I believe this is actually the same idea as (rand() * (max - min)) + min , only we discard the bits that push us to max . Instead of using the modulo operator, which may incorrectly bias results to lower values, we discard these bits and try again. Since pressing CSPRNG can cause re-sowing (which can block InputStream), I would like to avoid random bits. Henry points out that this code is biased against 0 and 257; Banthar demonstrates this in an example.
First edit: Henry reminded me that summation brings up a central limit theorem. I fixed the code above to get around this problem.
Second edit: The mechanical snail suggested I look at the source of Random.nextInt (). After reading it for a while, I realized that this problem is similar to the basic conversion problem. See answer below.