编者注:此代码示例来自 Rust 1.0 之前的版本,在语法上不是有效的 Rust 1.0 代码。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息。
我遇到了以下如何使用 Rust 生成随机数的示例,但它似乎不起作用。该示例没有显示它适用于哪个版本的 Rust,所以也许它已经过时了,或者也许我弄错了。
// 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);
}
当我尝试编译它时,出现以下错误:
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);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
同一页面(上面)上还有另一个示例(如下),可以正常工作。然而,尽管我可以调整它,但它并没有完全达到我想要的效果。
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)>());
}
如何使用 Rust(例如:
i64
)在给定范围(例如:0 到 n)内生成“简单”随机数?
Rng::gen_range
: 生成 0(含)和 100(不含)之间的随机数
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);
}
不要忘记将
rand
依赖项添加到 Cargo.toml:
[dependencies]
rand = "0.8"
编者注:此答案适用于 Rust 1.0 之前的版本,在 Rust 1.0 中无效。请参阅 Manoel Stilpen 的答案。
最近这个变化很大(抱歉!都是我造成的),在 Rust 0.8 中它被称为
gen_integer_range
(注意 URL 中的 /0.8/
而不是 /master/
,如果你使用的是 0.8, 需要阅读这些文档)。
警告一句:
.gen_integer_range
在很多方面都是完全错误的,新的.gen_range
没有不正确的问题。
master代码(其中
.gen_range
工作正常):
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);
}
Rng::gen_range
的文档指出:
此函数针对给定范围内仅生成单个样本的情况进行了优化。另请参阅
分布类型,如果重复从同一范围采样,可能会更快。Uniform
Uniform
可用于生成单个值:
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);
}
或者生成值的迭代器:
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);
}
random
API,它允许您轻松生成随机数,无需外部 crate。以下是 u64
的示例实现:
#![feature(random)] // requires nightly toolchain
fn random_u64_in_range(range: impl std::ops::RangeBounds<u64>) -> u64 {
use std::ops::Bound::*;
let min = match range.start_bound() {
Included(&num) => num,
Excluded(&num) => num + 1,
Unbounded => 0
};
let max = match range.end_bound() {
Included(&num) => num,
Excluded(&num) => num - 1,
Unbounded => u64::MAX
};
if min >= max {
return min; // alternatively, panic
}
let output_mask = u64::MAX >> (max - min).leading_zeros();
// Repeatedly generate random numbers until one is found within the range.
// A simpler method would be to return random() % (max - min) + min,
// but this could result in a slight bias in the generated values.
std::iter::repeat_with(|| std::random::random::<u64>() & output_mask)
.find(|&trial| trial <= max - min).unwrap() + min
}
fn main() {
let val = random_u64_in_range(..=10); // from 0 to 10, inclusive
println!("{}", val);
}
请注意,正确执行此操作有点棘手,因为
random() % (max - min) + min
的明显方法会导致有偏差的结果。这可以很容易地看出,(例如)如果你想生成一个从 1 到 3 的数字,你有三种可能的结果,但是没有办法将 2^64 个可能的 random()
值划分为三个相等的值团体。
为什么不直接使用模数呢?
let x = rng.gen<u32>() % 25
因此您的值将在 0 到 24 之间。如果您需要不同的范围,请添加偏移量。