# Generate random numbers in specific range

After googling a bit I couldn’t find a simple way to use a shell command to generate a random decimal integer number included in a specific range, that is between a minimum and a maximum.

I read about `/dev/random`, `/dev/urandom` and `\$RANDOM`, but none of these can do what I need.

Is there another useful command, or a way to use the previous data?

You can try `shuf` from GNU coreutils:

``````shuf -i 1-100 -n 1
``````

To generate a random integer variable between 5 and 10 (including both), use

``````echo \$(( RANDOM % (10 - 5 + 1 ) + 5 ))
``````

`%` works as a modulo operator.

There are probably better ways to convert the random variable `\$RANDOM` to a specific range. Do not use this for cryptographic applications or in cases you need real, equal-distributed random variables (like for simulations).

In the POSIX toolchest, you can use `awk`:

``````awk -v min=5 -v max=10 'BEGIN{srand(); print int(min+rand()*(max-min+1))}'
``````

Do not use that as a source to generate passwords or secret data for instance, as with most `awk` implementations, the number can easily be guessed based on the time that command was run.

With many `awk` implementations, that command run twice within the same second will generally give you the same output.

The `\$RANDOM` variable is normally not a good way to generated good random values. The output of `/dev/[u]random` need also to be converted first.

An easier way is to use higher level languages, like e.g. python:

To generate a random integer variable between 5 and 10 (5<=N<=10), use

``````python -c "import random; print random.randint(5,10)"
``````

Do not use this for cryptographic applications.

You can get the random number through `urandom`

`head -200 /dev/urandom | cksum`

Output:

`3310670062 52870`

To retrieve the one part of the above number.

`head -200 /dev/urandom | cksum | cut -f1 -d " "`

Then the output is

`3310670062`

Maybe the `UUID` (on Linux) can be used to retrieve the random number

``````\$ cat /proc/sys/kernel/random/uuid
``````

To get the random number between `70` and `100`

``````POSIXLY_CORRECT=1 awk -F - '{print(("0x"\$1) % 30 + 70)}
' /proc/sys/kernel/random/uuid
``````

# jot

On BSD and OSX you can use jot to return a single random (`-r`) number from the interval `min` to `max`, inclusive.

``````\$ min=5
\$ max=10
\$ jot -r 1 \$min \$max
``````

## Distribution problem

Unfortunately, the range and distribution of randomly generated numbers is influenced by the fact that jot uses double precision floating point arithmetic internally and printf(3) for output format, which causes rounding and truncation issues. Therefore, the interval’s `min` and `max` are generated less frequently as demonstrated:

``````\$ jot -r 100000 5 10 | sort -n | uniq -c
9918  5
20176 6
20006 7
20083 8
19879 9
9938  10
``````

On OS X 10.11 (El Capitan) this appears to have been fixed:

``````\$ jot -r 100000 5 10 | sort -n | uniq -c
16692 5
16550 6
16856 7
16579 8
16714 9
16609 10
``````

and…

``````\$ jot -r 1000000 1 10 | sort -n | uniq -c
100430 1
99965 2
99982 3
99796 4
100444 5
99853 6
99835 7
100397 8
99588 9
99710 10
``````

## Solving the distribution problem

For older versions of OS X, fortunately there are several workarounds. One is to use printf(3) integer conversion. The only caveat is that the interval maximum now becomes `max+1`. By using integer formatting, we get fair distribution across the entire interval:

``````\$ jot -w %i -r 100000 5 11 | sort -n | uniq -c
16756 5
16571 6
16744 7
16605 8
16683 9
16641 10
``````

## The perfect solution

Finally, to get a fair roll of the dice using the workaround, we have:

``````\$ min=5
\$ max_plus1=11  # 10 + 1
\$ jot -w %i -r 1 \$min \$max_plus1
``````

## Extra homework

See jot(1) for the gory math and formatting details and many more examples.

``````cat /dev/urandom | tr -dc 'a-fA-F0-9' | fold -w 8 | head -n 1
``````

This will generate an 8 digits long hexadecimal number.

To stay entirely within bash and use the `\$RANDOM` variable but avoid the uneven distribution:

``````#!/bin/bash
range=10
floor=20

if [ \$range -gt 32768 ]; then
echo 'range outside of what \$RANDOM can provide.' >&2
exit 1 # exit before entering infinite loop
fi

max_RANDOM=\$(( 2**15/\$range*\$range ))
r=\$RANDOM
until [ \$r -lt \$max_RANDOM ]; do
r=\$RANDOM
done
echo \$(( r % \$range + \$floor ))
``````

This example would provide random numbers from 20 through 29.

Explanation: Any `\$RANDOM` result greater than `2**15/\$range*\$range` is in an incomplete modulus fold within which the result of `\$r % \$range` has a max value of `2**15%\$range`, so results from 0 to `2**15%\$range` have weight of `2**15/\$range+1` and the value above have a weight of just `2**15/\$range`. The worst case scenario of the poor distribution is when the `2**15/\$range` is 1 and `2**15%\$range` is not 0. Here, we can see clearly the problem when the range is 2/3 of `2**15`, where half the results have twice the probability:

``````\$ range=\$((2**15*2/3)); for (( i=0; i<10000; i++));
> do [ \$((RANDOM%range) -le \$((range/2)) ]
> && ((le_10922++)) || ((gt_10922++)) ; done;
> echo le_10922 \$le_10922; echo gt_10922 \$gt_10922
le_10922 6748
gt_10922 3253
``````

`# echo \$(( \$RANDOM % 256 ))` will produce a “random” number between 0-255 in modern *sh dialects.

Distribution is good:

``````for (( i = 1 ; i <= 100000 ; i++ )) do echo \$(( RANDOM % (20 - 10 + 1 ) + 10 )) ; done | sort -n | uniq -c
``````

Gives:

``````  count value

9183 10
9109 11
8915 12
9037 13
9100 14
9138 15
9125 16
9261 17
9088 18
8996 19
9048 20
``````

Using RANDOM

``````MAX=999999                      #Upper Range
MIN=100000                      #Lower Range
DIFF=\$((MAX-MIN+1))             #+1 to inlcude upper limit
R=\$((\$((\$RANDOM%\$DIFF))+MIN))
``````

Using SHUF

``````MIN=1000
MAX=9999
COUNT=1                         #count of Random Numbers to be generated
shuf -i \$MIN-\$MAX -n \$COUNT
shuf -i 1000-9999 -n 1
``````

Using /dev/random

``````od -An -N2 -i /dev/random       #Generates a 2 byte Number, -N2=Generates 2 Random Number btween range 0-65535
``````

The best way to do this portably is with `od` (there’s no way to do it in portable POSIX shell without an external command, but at least this solution only has one such call). Here’s a complete function you can use:

``````# Usage: random [[MIN] MAX]
# Display a random number from MIN (def=0) to MAX (def=2^32-1) (inclusive)
random() {
n=\$(od -An -N4 -tu /dev/urandom) || return \$?
case \$# in
( 0 ) echo \$n ;;                                  # min=0  max=4294967295
( 1 ) echo \$(( n % (\$1 + 1) )) ;;                 # min=0  max=\$1
( 2 ) echo \$(( n % (\$2 + 1 - \$1) + \$1 )) ;;       # min=\$1 max=\$2
esac
}
``````

This generates a random unsigned integer and scopes it to optionally specified minimum and maximum values.

Examples:

``````\$ random      # a random integer between 0 and 4294967295 (2³²-1)
102618
\$ random 5    # a random integer between 0 and 5
5
\$ random 1 5  # a random integer between 1 and 5
3
``````

We all love one-liners, right? I managed to wedge this into 80 characters:

``````random(){ echo \$((\$(od -An -N4 -tu /dev/random)\${1+%(\${2+\$2- }\$1+1)\${2++\$1}}));}
``````

(Explanation removed for being too verbose, see revision 3 for detail.)

Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.