### Generating Random Numbers in Ruby

It can be useful in a range programs, typically games and simulations, to generate random numbers. While no computer can generate truly random numbers, Ruby does provide access to a method that will return *pseudorandom* numbers.

### The Numbers Aren't Actually Random

No computer can generate truly random numbers purely by computation. The best they can do is to generate *pseudorandom* numbers, which are a sequence of numbers that *appear *random but are not.

To a human observer, these numbers are indeed random. There will be no short repeating sequences, and, at least to the human observer, they'll be completely random. However, given enough time and motivation, the original *seed* can be discovered, the sequence recreated and the next number in the sequence guessed.

For this reason, the methods discussed in this article should probably not be used to generate numbers that must be cryptographically secure.

As mentioned above, pseudorandom number generators (PRNGs) must be *seeded* in order to produce sequences that differ each time a new random number is generated. Remember that no method is magical - these seemingly random numbers are generated using relatively simple algorithms and relatively simple arithmetic. By seeding the PRNG, you're starting it off at a different point every time. If you didn't seed it, it would generate the same sequence of numbers each time.

In Ruby, the **Kernel#srand** method can be called with no arguments. It will choose a random number seed based on the time, the process ID and a sequence number. Simply by calling **srand** anywhere at the beginning of your program, it will generate a different series of seemingly random numbers each time you run it. This method is called implicitly when the program starts up, and seeds the PRNG with the time and process ID (no sequence number).

### Generating Numbers

Once the program is running and **Kernel#srand** was either implicitly or explicitly called, the **Kernel#rand** method can be called. This method, called with no arguments, will return a random number from 0 to 1. In the past, this number was typically scaled to the maximum number you'd wish to generate and perhaps *to_i* called on it to convert it to an integer.

`# Generate an integer from 0 to 10 puts (rand() * 10).to_i`

However, Ruby makes things a bit easier if you're using Ruby 1.9.x. The **Kernel#rand** method can take a single argument. If this argument is a **Numeric** of any kind, Ruby will generate an integer from 0 up to (and not including) that number.

`# Generate a number from 0 to 10 # In a more readable way puts rand(10)`

However, what if you want to generate a number from 10 to 15? Typically, you'd generate a number from 0 to 5 and add it to 10. However, Ruby makes it easier.

You can pass a Range object to **Kernel#rand** and it will do just as you'd expect: generate a random integer in that range.

Make sure you pay attention to the two types of ranges. If you called **rand(10..15)**, that would generate a number from 10 to 15 *including* 15. Whereas **rand(10...15)** (with 3 dots) would generate a number from 10 to 15 *not including* 15.

`# Generate a number from 10 to 15 # Including 15 puts rand(10..15)`

### Non-Random Random Numbers

Sometimes you need a random-looking sequence of numbers, but need to generate the same sequence every time. For example, if you generate random numbers in a unit test, you should generate the same sequence of numbers every time.

A unit test that fails on one sequence should fail again the next time it's run, if it generated a difference sequence the next time, it might not fail. To do that, call **Kernel#srand** with a known and constant value.

`# Generate the same sequence of numbers every time # the program is run srand(5) # Generate 10 random numbers puts (0..10).map{rand(0..10)}`

### There is One Caveat

The implementation of **Kernel#rand** is rather un-Ruby. It doesn't abstract the PRNG in any way, nor does it allow you to instantiate the PRNG. There is one global state for the PRNG that all the code shares. If you change the seed or otherwise change the state of the PRNG, it may have a wider range of effect than you anticipated.

However, since programs expect the result of this method to be random (since that's its purpose), this will probably never be a problem. Only if the program expects to see an expected sequence of numbers, such as if it had called **srand** with a constant value, should it see unexpected results.