-
Notifications
You must be signed in to change notification settings - Fork 1
Description
To save on network calls, qrng.js requests a block of hexadecimal numbers from ANU. Converting this base-16 number to an arbitrary range results in an uneven distribution of random numbers depending on that range. The steps are:
- determine the range required (e.g.:
getInteger(200, 250)will have a range of 50) - determine how many hexadecimal characters we need to cover that range (from the above example, 2 hexadecimal characters are required to cover a range of 50)
- get that many hex characters from the qrng cache
- convert those hex characters to a base-10 number
- add that base-10 number to the minimum range (from the above example, 200)
- if the resulting number is greater than the maximum range (from the above example, 250) then subtract to find the excess and add that to the minimum
So suppose we call getInteger(0, 10) to generate a random character between 0 and 9 inclusive. This will extract a single hexadecimal character with a possible value of 0 to 15 inclusive. If the random hexadecimal character has a value of 10-15, then we shift that up such that the value becomes 0-5. This means that for a random base-10 integer between 0 and 9 (generated from a random base-16 number from ANU), you have the following possible outcomes:
| base-16 from ANU | generated base-10 |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| A | 0 |
| B | 1 |
| C | 2 |
| D | 3 |
| E | 4 |
| F | 5 |
Note that there is a 2/16 chance of selecting a 0-5 vs a 1/16 chance of selecting 6-9
This problem basically resembles this stackoverflow question. We're trying to fit a random number from the bin [1, 16] into an [a, b] bin where b - a might not equal 16. I'm not sure if there's some math or bit magic we can use to make this work, but I think we might simply have to resort to caching base-10 integers.