97

Editor's note: This code example is from a version of Rust prior to 1.0 and is not syntactically valid Rust 1.0 code. Updated versions of this code produce different errors, but the answers still contain valuable information.

I came across the following example of how to generate a random number using Rust, but it doesn't appear to work. The example doesn't show which version of Rust it applies to, so perhaps it is out-of-date, or perhaps I got something wrong.

// http://static.rust-lang.org/doc/master/std/rand/trait.Rng.html

use std::rand;
use std::rand::Rng;

fn main() {
    let mut rng = rand::task_rng();
    let n: uint = rng.gen_range(0u, 10);
    println!("{}", n);
    let m: float = rng.gen_range(-40.0, 1.3e5);
    println!("{}", m);
}

When I attempt to compile this, the following error results:

test_rand002.rs:6:17: 6:39 error: type `@mut std::rand::IsaacRng` does not
implement any method in scope named `gen_range`
test_rand002.rs:6    let n: uint = rng.gen_range(0u, 10);
                                   ^~~~~~~~~~~~~~~~~~~~~~
test_rand002.rs:8:18: 8:46 error: type `@mut std::rand::IsaacRng` does not
implement any method in scope named `gen_range`
test_rand002.rs:8    let m: float = rng.gen_range(-40.0, 1.3e5);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

There is another example (as follows) on the same page (above) that does work. However, it doesn't do exactly what I want, although I could adapt it.

use std::rand;
use std::rand::Rng;

fn main() {
    let mut rng = rand::task_rng();
    let x: uint = rng.gen();
    println!("{}", x);
    println!("{:?}", rng.gen::<(f64, bool)>());
}

How can I generate a "simple" random number using Rust (e.g.: i64) within a given range (e.g.: 0 to n)?

1

5 Answers 5

138

This generates a random number between 0 (inclusive) and 100 (exclusive) using Rng::gen_range:

use rand::Rng; // 0.8.5

fn main() {
    // Generate random number in the range [0, 99]
    let num = rand::thread_rng().gen_range(0..100);
    println!("{}", num);
}

Don't forget to add the rand dependency to Cargo.toml:

[dependencies]
rand = "0.8"
Sign up to request clarification or add additional context in comments.

Comments

28

Editor's note: This answer is for a version of Rust prior to 1.0 and is not valid in Rust 1.0. See Manoel Stilpen's answer instead.

This has been changing a lot recently (sorry! it's all been me), and in Rust 0.8 it was called gen_integer_range (note the /0.8/ rather than /master/ in the URL, if you are using 0.8 you need to be reading those docs).

A word of warning: .gen_integer_range was entirely incorrect in many ways, the new .gen_range doesn't have incorrectness problems.


Code for master (where .gen_range works fine):

use std::rand::{task_rng, Rng};

fn main() {
    // a number from [-40.0, 13000.0)
    let num: f64 = task_rng().gen_range(-40.0, 1.3e4);
    println!("{}", num);
}

3 Comments

I see that for 0.10 and master the documentation says to use rand::Rng static.rust-lang.org/doc/0.10/rand/index.html so it's a documentation bug probably
I get rust.rs:1:17: 1:25 error: unresolved import std::rand::task_rng. There is no task_rng` in std::rand rust.rs:1 use std::rand::{task_rng, Rng}; ^~~~~~~~ error: aborting due to previous error ` when I try to compile it with rustc 1.0.0-nightly (b4c965ee8 2015-03-02) (built 2015-03-03)
For people who stumble upon this question now: rand seems to have become an independent crate on its own, and the answer by Manoel Stilpen below, where you explicitly use that crate, works.
18

The documentation for Rng::gen_range states:

This function is optimised for the case that only a single sample is made from the given range. See also the Uniform distribution type which may be faster if sampling from the same range repeatedly.

Uniform can be used to generate a single value:

use rand::distributions::{Distribution, Uniform}; // 0.6.5

fn main() {
    let step = Uniform::new(0, 50);
    let mut rng = rand::thread_rng();
    let choice = step.sample(&mut rng);
    println!("{}", choice);
}

Playground

Or to generate an iterator of values:

use rand::distributions::{Distribution, Uniform}; // 0.6.5

fn main() {
    let step = Uniform::new(0, 50);
    let mut rng = rand::thread_rng();
    let choices: Vec<_> = step.sample_iter(&mut rng).take(10).collect();
    println!("{:?}", choices);
}

Playground

4 Comments

In Rust 1.15.1, I'm getting "unresolved name" from rand::thread_rng. play.rust-lang.org/…
I think something changed since every answer and even the documentation uses rand::thread_rng. By the way, rand is unstable now, so you have to add #![feature(rand)] to the top of your file and use the nightly rustc. All I want to do is test something; I'm this close to just using the C rand() function through FFI and calling it a day.
This works for me with Rust 1.7.0. Have to add rand = "0.3" into Cargo.toml file though.
As of rustc 1.42.0 (stable) with > rand 0.7 this appears to be the most accurate answer.
1

Since 2024, nightly Rust has had the random API, which allows you to generate easily random numbers with no external crates necessary. Here's an example implementation for i64:

#![feature(random)] // requires nightly toolchain
use std::random::random;

fn random_num_in_range(min: i64, max: i64) -> i64 {
    let range = max - min + 1;
    if range == 0 {
        random()
    } else {
        min + std::iter::repeat_with(random::<i64>)
            .find(|&trial| trial >= range.wrapping_neg() % range).unwrap() % range
    }
}

fn main() {
    let val = random_num_in_range(-2, 6); // from -2 to 6, inclusive
    println!("{}", val);
}

Note that getting this right is a little tricky, as the obvious method of random() % (max - min + 1) + min causes biased results. This can be easily seen by the fact that (for example) if you want to generate a number from 1 to 3, you have three possible results, but there is no way to partition 2^64 possible values of random() into three equal groups.

There's a good explanation of the different algorithms you can use for this task here: https://www.pcg-random.org/posts/bounded-rands.html

Comments

-4

And why don't you just use a modulo?

let x = rng.gen<u32>() % 25

so your values will be between 0 and 24. Add an offset if you need a different range.

1 Comment

This will give you numbers in range 0..25, but their distribution will not be uniform. It may be negligible with 25, since it is lot smaller than u32::MAX. But if you used this with range 0..4_000_000_000, you would find that you get the numbers in 0..294_649_297 twice as often as those in 294_649_297..4_000_000_000.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.