Как сгенерировать случайное число в заданном диапазоне в Rust?
Полный ответ: генерация случайных чисел в Rust с крейтом `rand`
Вы на правильном пути! Для генерации случайных чисел в Rust действительно используется крейт rand. Однако с момента вашего вопроса синтаксис немного изменился (особенно в версии 0.8+). Давайте разберём всё по шагам.
Шаг 1: Добавление зависимости в Cargo.toml
Откройте файл Cargo.toml вашего проекта и добавьте под секцией [dependencies] строку:
[dependencies]
rand = "0.8"
После этого выполните cargo build — Cargo автоматически скачает крейт.
Шаг 2: Импорт и использование в коде
В современном Rust (версия 1.50+) метод gen_range принимает диапазон в виде start..=end (включительно) или start..end (исключительно). Вот рабочий пример:
use rand::Rng;
fn main() {
// Создаём генератор случайных чисел (thread-local)
let mut rng = rand::thread_rng();
// Генерация числа от 1 до 100 включительно
let secret_number: u32 = rng.gen_range(1..=100);
println!("Секретное число: {}", secret_number);
// Другие примеры:
let float_num: f64 = rng.gen_range(0.0..1.0); // вещественное от 0 до 1 (не включая 1)
let dice_roll: u8 = rng.gen_range(1..=6); // бросок кубика
}
Почему ваш код не работал?
- Не хватало импорта: нужно добавить
use rand::Rng;— это трейт, который предоставляет методыgen_range,genи другие. - Устаревший синтаксис: в версии
rand 0.8методgen_rangeпринимает один аргумент-диапазон (1..=100), а не два числа (1, 101). Двухаргументный синтаксис был вrand 0.7и удалён. - Не использовался
mut:thread_rng()возвращает изменяемый генератор, поэтому переменная должна бытьlet mut rng.
Дополнительные возможности
Крейт rand умеет генерировать разные типы:
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
// Случайное число из заданного набора (выбор элемента)
let choices = ['A', 'B', 'C', 'D'];
let random_choice = choices[rng.gen_range(0..choices.len())];
// Случайный bool
let coin_flip: bool = rng.gen();
// Случайное число с нормальным распределением (требуется крейт rand_distr)
// use rand_distr::{Normal, Distribution};
// let normal = Normal::new(0.0, 1.0).unwrap();
// let sample = normal.sample(&mut rng);
}
Полный рабочий пример для игры-угадайки
use rand::Rng;
use std::io;
fn main() {
println!("Угадайте число от 1 до 100!");
let secret_number = rand::thread_rng().gen_range(1..=100);
loop {
println!("Введите ваше предположение:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Ошибка чтения строки");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
match guess.cmp(&secret_number) {
std::cmp::Ordering::Less => println!("Слишком мало!"),
std::cmp::Ordering::Greater => println!("Слишком много!"),
std::cmp::Ordering::Equal => {
println!("Вы угадали!");
break;
}
}
}
}
Важно: Если вы используете rand версии 0.7 или ниже, синтаксис будет другим. Всегда проверяйте документацию по крейту на docs.rs.
Альтернативный подход: генерация без крейта rand (для простых случаев)
Если вам нужно только одно случайное число и вы не хотите подключать внешний крейт, можно использовать встроенный std::time::SystemTime для генерации псевдослучайного числа на основе времени. Однако это не рекомендуется для криптографии или игр, где нужна настоящая случайность, но для обучения подойдёт.
use std::time::{SystemTime, UNIX_EPOCH};
fn simple_random(min: u32, max: u32) -> u32 {
let duration = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
// Берём наносекунды и используем как seed
let nanos = duration.subsec_nanos() as u64;
let range = max - min + 1;
// Простой линейный конгруэнтный генератор (для демонстрации)
let result = (nanos * 6364136223846793005 + 1442695040888963407) % (range as u64);
min + (result as u32)
}
fn main() {
let secret = simple_random(1, 100);
println!("Случайное число (без крейта): {}", secret);
}
Минусы этого подхода:
- Числа будут повторяться, если вызывать функцию быстро (в пределах одной наносекунды).
- Распределение неравномерное — некоторые числа будут выпадать чаще.
- Не подходит для серьёзных проектов.
Поэтому для реальных задач всегда используйте крейт rand — он оптимизирован, безопасен и даёт качественные случайные числа.