Random Number
Generate Random Number
Computers generate random numbers using two main methods:
- True Random Number Generators (TRNGs) that rely on inherently random physical and unpredictable processes such as radioactive decay, mouse movements, fan noise, etc and convert them into random number.
- Pseudo-Random Number Generators (PRNGs): uses deterministic algorithm that start with an initial seed value and quickly produce a deterministic sequence of numbers that appear random. PRNGs are the ones we use.
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); if rand::random() { // generate a boolean println!("char: {}", rand::random::<char()>); // generate a random unicode char } let n1: u8 = rng.gen(); // generate a u8 int let n2: f64 = rng.gen(); // generate a f64 between 0-1 println!("Random u8: {}", n1); println!("Random f64: {}", n2); println!("Random u32: {}", rng.gen::<u32>()); println!("Random i32: {}", rng.gen::<i32>()); println!("Random float: {}", rng.gen::<f64>()); // range println!("Integer: {}", rng.gen_range(0..10)); // [0,10) println!("Float: {}", rng.gen_range(0.0..10.0)); let mut nums: Vec<i32> = (1..100).collect(); nums.shuffle(&mut rng); }
By default, rand crate have uniform distribution, which we can aso generate as follows:
use rand::distributions::{Distribution, Uniform}; fn main() { let mut rng = rand::thread_rng(); let die = Uniform::from(1..7); loop { let throw = die.sample(&mut rng); println!("Roll the die: {}", throw); if throw == 6 { break; } } }
We can generate Random Number with other distributions from rand_distr
use rand_distr::{Distribution, Normal, NormalError}; use rand::thread_rng; fn main() -> Result<(), NormalError> { let mut rng = thread_rng(); let normal = Normal::new(1.0, 2.0)?; // (μ,σ^2) // other constructs are also available let v = normal.sample(&mut rng); println!("{} is from a N(1, 4) distribution", v); Ok(()) }
Generate random set of alphanumeric ASCII characters for example to create a password
use rand::{thread_rng, Rng}; use rand::distributions::Alphanumeric; fn main() { let rand_string: String = thread_rng() .sample_iter(&Alphanumeric) .take(30) .map(char::from) .collect(); println!("{}", rand_string); }
To include user defined bytestring in the password
fn main() { use rand::Rng; const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789)(*&^%$#@!~"; const PASSWORD_LEN: usize = 30; let mut rng = rand::thread_rng(); let password: String = (0..PASSWORD_LEN) .map(|_| { let idx = rng.gen_range(0..CHARSET.len()); CHARSET[idx] as char }) .collect(); println!("{:?}", password); }
Custom Random Number Generator
use rand::Rng; use rand::distributions::{Distribution, Standard}; #[derive(Debug)] struct Point { x: i32, y: i32, } impl Distribution<Point> for Standard { //implement Distribution trait on the new type Point for Standard (generic RV dist) fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point { let (rand_x, rand_y) = rng.gen(); Point { x: rand_x, y: rand_y, } } } fn main() { let mut rng = rand::thread_rng(); let rand_tuple = rng.gen::<(i16, bool, f64)>(); // random tuple of our choice let rand_point: Point = rng.gen(); println!("Random tuple: {:?}", rand_tuple); println!("Random Point: {:?}", rand_point); }