5.1.2. 生成范围内随机数
问题:
你想从一个自定义标量区间内生成随机数。
解决方案:
我们继续使用 rand crate 来解决此问题。rand crate 中有一个产生范围区间的方法 Rng::gen_range
,可以在半开放的 [低位,高位]
范围内生成一个随机值,随机值包含低位
,不包含高位
。比如我们在 [0, 10)
范围内生成一个随机值。
以下实例代码引用自开源书籍项目《Cookin’ with Rust》,笔者在其基础上稍作修改。
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); println!(" 整数: {}", rng.gen_range(0..10)); // 半开放范围取随机值,即包括`低位`而不包括`高位` println!(" 浮点数: {}", rng.gen_range(0.0..10.0)); }
代码第 1 行,我们使用 use
关键字将 rand::Rng
引入作用域。rand::Rng
是在 RngCore
trait 上自动实现的扩展 trait,它实现了高层次的泛型方法。
代码第 4 行,由系统创建本地线程,作用为延迟初始化的随机数生成器。
代码第 6,7 行,分别从半开放范围取整型(0,10)和浮点型(0.0,10.0)随机值,即包括低位
而不包括高位
。
构建并运行后,结果大抵如下所示。
整数: 8
浮点数: 5.352798350588619
注:你的运行结果值和笔者运行结果不一定相同。
讨论:
Rng::gen_range
方法在 [低位,高位]
范围内生成一个随机值。此范围为半开放范围,即包括低位
而不包括高位
。此函数针对给定范围内仅生成一个样本值的情况进行了优化。另外,此函数为均匀分布类型,如果从相同的范围重复抽样取值,执行速度将会更快。
Uniform
是一个结构体,表示样本值均匀地分布在两个界限之间。Uniform::new
和 Uniform::new_inclusive
构造给定范围内的均匀分布采样;这些函数可能会预先做一些额外的工作,以便更快地对多个值进行采样。必须特别注意:确保四舍五入不会导致采样值小于(<)低位或者大于等于(>=)高位。
均匀分布:在概率论和统计学中,均匀分布也叫矩形分布,它是对称概率分布,在相同长度间隔的分布概率是可能相等的。
使用 Uniform
模块可以得到均匀分布的值。下述代码和上述代码具有相同的效果,但在相同范围内重复生成数字时,下述代码性能可能会更好。
以下实例代码引用自开源书籍项目《Cookin’ with Rust》,笔者在其基础上稍作修改。
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!(" 丢一次骰子: {}", throw); if throw == 6 { break; } } }
本实例模拟丢骰子的程序。
代码第 1 行,我们使用 use
关键字将均匀分布模块 rand::distributions::{Distribution, Uniform};
引入作用域。其中 Distribution
trait 必须引入,其将自动实现随机值的取值方法。若不引入,代码第 8 行的 sample
方法将不能使用,控制会输出如下错误:
error[E0599]: no method named `sample` found for struct `Uniform<{integer}>` in the current scope
--> examples/rand-range-uniform.rs:8:25
|
8 | let throw = die.sample(&mut rng);
| ^^^^^^ method not found in `Uniform<{integer}>`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use rand::distributions::Distribution;
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
error: could not compile `randomness`
To learn more, run the command again with --verbose.
代码第 4 行,由系统创建本地线程,作用为延迟初始化的随机数生成器。
代码第 5 行,制定了均匀分布取随机值的半开放范围(1,7),包括 1
而不包括 7
。
代码第 8 行,使用 Distribution
trait 实现的 sample
方法进行随机值的半开放范围取值。
构建并运行后,结果大抵如下所示。
丢一次骰子: 4
丢一次骰子: 1
丢一次骰子: 5
丢一次骰子: 4
丢一次骰子: 2
丢一次骰子: 6
注:你的运行结果值,包括丢骰子的次数和骰子面值,都和笔者运行结果不一定相同。