How are the random numbers made? Well, they are Made With Math!



Instead of using the Arduino random number generator function random(), I decided to write my own Random Number Generator (RNG), just for fun.

It is based on the logistic map, which is the simplest example of deterministic chaos. Here's how it works:

Suppose x is some real value between 0 and 1, then calculate: x*r*(1-x), where r=3.9. The result is your next 'x'. Repeat ad infinitum. This will give you a series of numbers between 0 and 1, as in the first picture, where this process is started for the initial value of x=0.1 (red) and also x=0.1001 (blue).

Now here's the cool part: no matter how close you choose two different initial conditions, if they are not exactly equal, the resulting series of numbers will eventually diverge. This is called 'Sensitive dependence on initial conditions'.

Mathematically, the map equation x*r*(1-x) is a parabola. As shown in the 2nd figure, you can graphically determine the x-series using what is known as a cobweb construction: start from x on the horizontal axis, find the function value on the y-axis, then reflect against a straight line at 45 degrees angle going through the origin. Repeat. As shown for the red and blue series, even if close initially, they completely diverge after about 30 iterations.

Now, where does the 'r=3.9' number come from? It turns out that for low values of r, we get only two alternating x-values. Increasing the r-parameter will then at some point switch to an oscillation between 4, 8, 16 values etc. These branchings or bifurcations come more and more rapidly as r is increased, in what is called a 'period doubling route to chaos'. A plot with r on the horizontal axis and many x-iterates overlapped vertically will result in what is known as a bifurcation plot (3rd figure). For r=3.9, the map is fully chaotic.

So if we calculate many x-updates and sample from them, we get a random number? Well no, at this point it would be a Pseudo Random Number generator (PRNG), since if we always start from the same initial value (after coming out of reset), we would always get the same sequence; aka deterministic chaos. This is where the entropy-generator comes in, which seeds the logistic map with a number created from electric noise found in the environment.



In words, the random number generator code does this:



- Measure the voltage from the entropy generator on pin A0. Keep only the 4 least significant bits.

- Shift these 4 bits into a 'seed' value, repeat 8 times to get a 32-bit floating point seed.

- Rescale the seed between 0 and 1.

- Calculate the average of this seed and x, the current state of the logistic map.

- Advance the logistic map many (64) steps.

- Extract a single bit from the logistic map state x by checking some insignificant decimal.

- Shift that bit into the final result.

- Repeat all steps above 20 times.





Note: In the code, the Serial.println and Serial.begin are outcommented. Remove the // to check the generated random numbers on the serial monitor.

To be fair, I haven't statistically checked the quality of the random numbers (e.g. NIST test suite) but they seem to be OK.