By the way, the example snippet given to "echo a random number between 1 and 10" is incorrect, pedantically speaking. It's random, but not uniformly so. It's biased towards lower numbers (1-6).
> $ for((i=1;i<10000;i+=1)); do cat /dev/urandom | od -N 1 -An -i | awk '{print $1 % 10 + 1}' >> rand.txt ; done
> $ cat rand.txt | sort | uniq -c
1051 1
932 10
1012 2
1042 3
983 4
1015 5
1042 6
1035 7
992 8
995 9You can see it quite intuitively if you iterate over all possible numbers between 0 and 255:
$ (for i in {0..255}; do; echo $i | awk '{print $1 % 10 + 1}'; done) | sort -n | uniq -c
26 1
26 2
26 3
26 4
26 5
26 6
25 7
25 8
25 9
25 10What do you think each byte from /dev/(u)random is?
R % 10 + 1
The problem is that 10 does not evenly divide 256, hence for large R, the mapping will be incomplete. Specifically, 250 => 1
251 => 2
252 => 3
253 => 4
254 => 5
255 => 6
with no more random numbers available to yield results 7, 8, 9 and 10. R * 10 / 256 + 1
EDIT: I am wrong, this still has bias.And indeed this is how Python does it
https://github.com/python/cpython/blob/e37ac5fbb6de593521cf2...
https://github.com/python/cpython/blob/e37ac5fbb6de593521cf2...