Loading page…
Rust walkthroughs
Loading page…
Rand is the standard random number generation library for Rust. It provides thread-local random number generators, various distributions (uniform, normal, exponential), cryptographically secure random generation, and utilities for shuffling and sampling. Rand uses the ChaCha algorithm by default for reproducibility across platforms.
Key concepts:
rand::Rng trait — core interface for generating random valuesrandom() function — quick one-off random valuesthread_rng() — thread-local generator (most common)Rand is essential for simulations, games, sampling, testing, and cryptography.
# Cargo.toml
[dependencies]
rand = "0.8"use rand::Rng;
fn main() {
// Quick random value
let n: i32 = rand::random();
println!("Random i32: {}", n);
// Random boolean
let b: bool = rand::random();
println!("Random bool: {}", b);
// Thread-local generator (preferred)
let mut rng = rand::thread_rng();
// Random integer in range [1, 100)
let dice_roll: i32 = rng.gen_range(1..=6);
println!("Dice roll: {}", dice_roll);
// Random float in range [0.0, 1.0)
let probability: f64 = rng.gen::<f64>();
println!("Random f64: {}", probability);
// Random float in custom range
let percent: f64 = rng.gen_range(0.0..100.0);
println!("Random percentage: {:.2}%", percent);
}use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
// Integer ranges
let small: i32 = rng.gen_range(1..10); // [1, 10)
let inclusive: i32 = rng.gen_range(1..=100); // [1, 100]
let negative: i32 = rng.gen_range(-50..50); // [-50, 50)
let byte: u8 = rng.gen_range(0..=255); // [0, 255]
println!("Small: {}, Inclusive: {}, Negative: {}, Byte: {}",
small, inclusive, negative, byte);
// Float ranges
let unit: f64 = rng.gen_range(0.0..1.0); // [0.0, 1.0)
let angle: f64 = rng.gen_range(0.0..std::f64::consts::TAU);
let temp: f64 = rng.gen_range(-273.15..1000.0);
println!("Unit: {:.4}, Angle: {:.4}, Temp: {:.2}", unit, angle, temp);
// Range types can be stored
let range = 10..20;
let in_range: i32 = rng.gen_range(range);
println!("In range: {}", in_range);
}use rand::{Rng, seq::SliceRandom};
fn main() {
let mut rng = rand::thread_rng();
// Choose single element
let choices = ['a', 'b', 'c', 'd', 'e'];
let choice = choices.choose(&mut rng);
println!("Chosen: {:?}", choice);
// Choose multiple elements (with replacement)
let samples: Vec<&char> = choices.choose_multiple(&mut rng, 3).collect();
println!("Samples: {:?}", samples);
// Choose multiple (without replacement)
let mut shuffled = vec![1, 2, 3, 4, 5];
shuffled.shuffle(&mut rng);
println!("Shuffled: {:?}", shuffled);
// Partial shuffle
let mut numbers: Vec<i32> = (1..=100).collect();
numbers.partial_shuffle(&mut rng, 5);
println!("First 5 shuffled: {:?}", &numbers[..5]);
// Choose from String
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let random_char = alphabet.chars().choose(&mut rng);
println!("Random letter: {:?}", random_char);
// Weighted choice
let weighted_choices = [
('a', 4), // weight 4
('b', 1), // weight 1
('c', 3), // weight 3
];
let weights: Vec<u32> = weighted_choices.iter().map(|(_, w)| *w).collect();
let chars: Vec<char> = weighted_choices.iter().map(|(c, _)| *c).collect();
let dist = rand::distributions::WeightedIndex::new(&weights).unwrap();
let idx = dist.sample(&mut rng);
println!("Weighted choice: {}", chars[idx]);
}use rand::Rng;
use rand::distributions::{Distribution, Uniform, Alphanumeric, Standard};
fn main() {
let mut rng = rand::thread_rng();
// Uniform distribution (reusable)
let die = Uniform::from(1..=6);
let rolls: Vec<i32> = (0..10).map(|_| die.sample(&mut rng)).collect();
println!("Dice rolls: {:?}", rolls);
// Uniform for floats
let percent_dist = Uniform::from(0.0..100.0);
let percents: Vec<f64> = (0..5).map(|_| percent_dist.sample(&mut rng)).collect();
println!("Percents: {:?}", percents);
// Standard normal distribution (mean=0, std=1)
let normal = rand::distributions::StandardNormal;
let normals: Vec<f64> = (0..5).map(|_| normal.sample(&mut rng)).collect();
println!("Standard normal: {:?}", normals);
// Normal distribution with custom parameters
let normal = rand_distr::Normal::new(100.0, 15.0).unwrap();
let iq_scores: Vec<f64> = (0..5).map(|_| normal.sample(&mut rng)).collect();
println!("IQ scores: {:?}", iq_scores);
// Alphanumeric characters
let code: String = (0..8)
.map(|_| rng.sample(Alphanumeric) as char)
.collect();
println!("Random code: {}", code);
// Using Standard distribution (default for types)
let values: Vec<i32> = (0..5).map(|_| rng.sample(Standard)).collect();
println!("Standard samples: {:?}", values);
}use rand::{Rng, SeedableRng};
use rand::rngs::StdRng;
fn main() {
// Create seeded generator from seed
let seed = 42u64;
let mut rng1 = StdRng::seed_from_u64(seed);
let mut rng2 = StdRng::seed_from_u64(seed);
// Both generators produce identical sequences
let seq1: Vec<u32> = (0..5).map(|_| rng1.gen()).collect();
let seq2: Vec<u32> = (0..5).map(|_| rng2.gen()).collect();
println!("Sequence 1: {:?}", seq1);
println!("Sequence 2: {:?}", seq2);
println!("Match: {}", seq1 == seq2);
// Seed from entropy (random seed)
let mut rng = StdRng::from_entropy();
let random_values: Vec<i32> = (0..5).map(|_| rng.gen()).collect();
println!("From entropy: {:?}", random_values);
// Use seed for reproducible simulations
println!("\nReproducible simulation:");
run_simulation(12345);
run_simulation(12345); // Same results
}
fn run_simulation(seed: u64) {
let mut rng = StdRng::seed_from_u64(seed);
let results: Vec<i32> = (0..5).map(|_| rng.gen_range(1..=100)).collect();
println!("Simulation results: {:?}", results);
}use rand::Rng;
use rand::distributions::{Distribution, Standard};
#[derive(Debug)]
struct Point {
x: f64,
y: f64,
}
// Implement Distribution for custom type
impl Distribution<Point> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
Point {
x: rng.gen(),
y: rng.gen(),
}
}
}
#[derive(Debug)]
enum Direction {
Up,
Down,
Left,
Right,
}
impl Distribution<Direction> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Direction {
match rng.gen_range(0..4) {
0 => Direction::Up,
1 => Direction::Down,
2 => Direction::Left,
_ => Direction::Right,
}
}
}
#[derive(Debug)]
struct Color {
r: u8,
g: u8,
b: u8,
}
impl Distribution<Color> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Color {
Color {
r: rng.gen(),
g: rng.gen(),
b: rng.gen(),
}
}
}
fn main() {
let mut rng = rand::thread_rng();
// Generate random Point
let point: Point = rng.gen();
println!("Random point: ({:.2}, {:.2})", point.x, point.y);
// Generate random Direction
let dirs: Vec<Direction> = (0..5).map(|_| rng.gen()).collect();
println!("Directions: {:?}", dirs);
// Generate random Color
let color: Color = rng.gen();
println!("Random color: RGB({}, {}, {})", color.r, color.g, color.b);
}use rand::Rng;
use rand::rngs::OsRng;
fn main() {
// OsRng uses the operating system's secure random source
let mut rng = OsRng;
// Generate secure random bytes
let mut key = [0u8; 32];
rng.fill(&mut key);
println!("Secure key: {:x?}", key);
// Generate secure random numbers
let secure_int: u64 = rng.gen();
println!("Secure integer: {}", secure_int);
// Generate secure token
let token: String = (0..32)
.map(|_| rng.gen::<u8>() as char)
.collect();
println!("Token (bytes as chars): {:?}", token);
// Better: hex-encoded token
let token_bytes: [u8; 16] = rng.gen();
let hex_token: String = token_bytes.iter().map(|b| format!("{:02x}", b)).collect();
println!("Hex token: {}", hex_token);
// UUID-like identifier
let uuid: [u8; 16] = rng.gen();
println!("UUID bytes: {:02x?}", uuid);
}use rand::Rng;
use rand::seq::SliceRandom;
fn main() {
let mut rng = rand::thread_rng();
// Shuffle a vector in place
let mut cards: Vec<&str> = vec![
"A♠", "2♠", "3♠", "4♠", "5♠", "6♠", "7♠", "8♠", "9♠", "10♠", "J♠", "Q♠", "K♠",
"A♥", "2♥", "3♥", "4♥", "5♥", "6♥", "7♥", "8♥", "9♥", "10♥", "J♥", "Q♥", "K♥",
];
cards.shuffle(&mut rng);
println!("Shuffled hand: {:?}", &cards[..5]);
// Generate a random permutation
let mut permutation: Vec<usize> = (0..10).collect();
permutation.shuffle(&mut rng);
println!("Permutation: {:?}", permutation);
// Check if shuffled
let original: Vec<i32> = (1..=10).collect();
let mut shuffled = original.clone();
shuffled.shuffle(&mut rng);
println!("Original: {:?}", original);
println!("Shuffled: {:?}", shuffled);
println!("Is shuffled: {}", original != shuffled);
// Sample without replacement
let numbers: Vec<i32> = (1..=1000).collect();
let sample: Vec<&i32> = numbers.choose_multiple(&mut rng, 5).collect();
println!("Sample of 5 from 1000: {:?}", sample);
}use rand::Rng;
use rand::distributions::Alphanumeric;
use rand::seq::IteratorRandom;
fn main() {
let mut rng = rand::thread_rng();
// Generate random password
let password: String = (0..12)
.map(|_| rng.sample(Alphanumeric) as char)
.collect();
println!("Password: {}", password);
// Generate random hex string
let hex: String = (0..8)
.map(|_| format!("{:02x}", rng.gen::<u8>()))
.collect();
println!("Hex string: {}", hex);
// Pick random element from iterator
let random_number = (1..=1000).choose(&mut rng);
println!("Random from iterator: {:?}", random_number);
// Coin flip
let heads = rng.gen_bool(0.5); // 50% chance
println!("Coin flip: {}", if heads { "Heads" } else { "Tails" });
// Loaded die (30% chance of success)
let success = rng.gen_bool(0.3);
println!("Success (30%): {}", success);
// Random percentage
let pct = rng.gen_ratio(1, 4); // 25% chance
println!("25% chance: {}", pct);
// Random index
let items = vec!["apple", "banana", "cherry", "date", "elderberry"];
let idx = rng.gen_range(0..items.len());
println!("Random fruit: {}", items[idx]);
// Fill array with random values
let mut buffer = [0u8; 16];
rng.fill(&mut buffer);
println!("Random buffer: {:02x?}", buffer);
}use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let total_points = 1_000_000;
let mut inside_circle = 0;
for _ in 0..total_points {
let x: f64 = rng.gen_range(-1.0..=1.0);
let y: f64 = rng.gen_range(-1.0..=1.0);
if x * x + y * y <= 1.0 {
inside_circle += 1;
}
}
let pi_estimate = 4.0 * (inside_circle as f64) / (total_points as f64);
println!("Pi estimate: {:.6}", pi_estimate);
println!("Actual pi: {:.6}", std::f64::consts::PI);
println!("Error: {:.6}", (pi_estimate - std::f64::consts::PI).abs());
}rand::random() for quick one-off random valuesrand::thread_rng() for a thread-local generator (most common)rng.gen::<T>() for a random value of type Trng.gen_range(start..end) for values in a range (exclusive)rng.gen_range(start..=end) for inclusive rangeSliceRandom::choose() picks a random element from a sliceSliceRandom::shuffle() shuffles a slice in placeIteratorRandom::choose() picks from an iteratorWeightedIndex samples with probability weightsUniform::from(range) creates a reusable distributionrand_distr::Normal::new(mean, std) for normal distributionStdRng::seed_from_u64(seed) for reproducible sequencesOsRng for cryptographically secure random numbersDistribution<T> for Standard to make custom types randomly generatablerng.gen_bool(p) returns true with probability prng.fill(&mut slice) fills a buffer with random bytes