2.11 Random

At times you may wish to generate a random number. Rust’s standard library does not contain any form of function to generate random numbers. We’re thus presented with two possibilities—make a random number generator ourselves or make use of a dependency available from Cargo’s user crate repository. For now, we’re going to stick with the latter.

Dependencies

Before we can start generating random numbers, we need to learn a little about dependencies. Start off by opening up your Cargo.toml file located inside your project folder.

[package]
name = "project"
version = "0.1.0"
authors = ["John Doe <john@example.com>"]

[dependencies]

That sure hasn’t changed much since last we looked into it. This time around, we’re going to pay attention to the dependencies section. Let's add the rand dependency:

[dependencies]
rand = "0.3"

You can locate this crate on Cargo’s user crate repository following this link. At the time this section on randomization was written, rand was in version 0.3.15. You can clearly see that this isn’t what we’re defining it as in the file, can you now?

We’re defining it as 0.3—this is not the actual case, we’re rather defining it as ^0.3. Regular version numbers like 0.3 are shorthand for that number preceeded by ^—meaning any version compatible with that version in particular. 0.3.15 is in fact compatible with 0.3.

Running

Upon running our project, we’ll notice that a whole lot of things are downloading:

 Updating registry https://github.com/rust-lang/crates.io-index Compiling libc v0.2.18 Compiling rand v0.3.15 Compiling random v0.1.0 (file:///C:/h/Bootcamp/calculator/random)  Finished debug [unoptimized + debuginfo] target(s) in 4.45 secs   Running target\debug\random.exe

This just successfully downloaded the rand dependency—meaning we all of a sudden are extraordinarily close to generating random numbers, now that we have the required dependencies.

Random

It’s exceptionally easy to generate a random number once you have retrieved the required dependency. Right before that, however, we need to tell Rust that we have an external package that we’d like to use, as well as use the parts of rand we’ll be using for this example:

extern crate rand;

use rand::{Rng, SeedableRng, StdRng};

See how we added {} during our use—this uses many things at one time from the saem dependency.

Seeds

There's always a seed for pseudorandom number generators, whether it be computer-based or personally entered by a human being. Depending on the seed of a pseudorandom number generator, it will return a sequence of numbers following that particular seed. If the seed is the same on two different pseudorandom number generators running on the same algorithms, they will generate identical sequences of numbers.

Computer-based seeding

Let’s let out computer handle the seeding for us:

let mut rng = rand::thread_rng();
println!("{}", rng.gen_range(1, 11));

On the first line we use thread_rng to retrieve a random number generator that is seeded using our computer—sometimes this is based on our system time, depending on the pseudorandom number generator. On the second line, we print out a random number that is generated using the rng generator from line one. gen_range will generate a random number between one and ten, including ten.

Let’s check its output:

5

If that number is the same for you as it is for me, there’s only a one in ten chance for that occuring. You sure have a lot of luck inside that huge mind of yours—or whatever made your generator generate the same number as mine.

Personal seeding

When you feel like you want to know beforehand what numbers are about to pop up, how about some homemade s—auce—eeding? Let’s go for it:

let seed: &[_] = &[7, 6, 2];
let mut rng: StdRng = SeedableRng::from_seed(seed);
println!("{}", rng.gen_range(1, 11));

Depending on the seed, the random number generator will always generate its values following the same order. The numbers generated will still be located in between one and ten, but if you change the seed, the numbers will change too.

The number generated using the above, will always be 3. If yours is something else using the same seed, you sure are one odd person.

Full-size numbers

You may choose to generate numbers according to the maximum capacity of a generic type. This works with both aforementioned types of pseudorandom number generators, as they are all based off of the same structure:

println!("{}", rng.gen::<i32>());

The type of generic type may be changed by inserting something other than i32 inside the <>.

Exercises

  • Create a classical guessing game, where the user attempts to guess a random number and gets told whether or not the number is higher or lower than his current guess—exiting upon guessing the correct number as well as congratulating the user for such a good guess.
  • Use the first exercise and add a guess count to it that you print out when the user successfully guesses the correct number.

Moreover

Pseudorandom number generators can be used for a lot of things—imagine having to randomize cards inside a deck or even entire landscapes? This sure is poweful knowledge!

Input