新增章节 [Cookbook - 生成随机数]

pull/696/head
sunface 3 years ago
parent e4f418141c
commit 5a2251f61f

@ -263,28 +263,30 @@
- [HashMap todo](std/hashmap.md) - [HashMap todo](std/hashmap.md)
- [Iterator 常用方法 todo](std/iterator.md) - [Iterator 常用方法 todo](std/iterator.md)
- [CookBook todo](cases/intro.md) - [CookBook doing](cookbook/intro.md)
- [命令行解析 todo](cases/cmd.md) - [常用算法]()
- [配置文件解析 todo](cases/config.md) - [生成随机值](cookbook/algos/randomness.md)
- [编解码 todo](cases/encoding/intro.md) - [命令行解析 todo](cookbook/cmd.md)
- [JSON](cases/encoding/json.md) - [配置文件解析 todo](cookbook/config.md)
- [CSV](cases/encoding/csv.md) - [编解码 todo](cookbook/encoding/intro.md)
- [protobuf](cases/encoding/protobuf.md) - [JSON](cookbook/encoding/json.md)
- [文件系统 todo](cases/file/intro.md) - [CSV](cookbook/encoding/csv.md)
- [文件读写](cases/file/file.md) - [protobuf](cookbook/encoding/protobuf.md)
- [目录操作](cases/file/dir.md) - [文件系统 todo](cookbook/file/intro.md)
- [网络通信 todo](cases/protocol/intro.md) - [文件读写](cookbook/file/file.md)
- [HTTP](cases/protocol/http.md) - [目录操作](cookbook/file/dir.md)
- [TCP](cases/protocol/tcp.md) - [网络通信 todo](cookbook/protocol/intro.md)
- [UDP](cases/protocol/udp.md) - [HTTP](cookbook/protocol/http.md)
- [gRPC](cases/protocol/grpc.md) - [TCP](cookbook/protocol/tcp.md)
- [数据库访问 todo](cases/database.md) - [UDP](cookbook/protocol/udp.md)
- [正则表达式 todo](cases/regexp.md) - [gRPC](cookbook/protocol/grpc.md)
- [加密解密 todo](cases/crypto.md) - [数据库访问 todo](cookbook/database.md)
- [时间日期](cases/date.md) - [正则表达式 todo](cookbook/regexp.md)
- [开发调试 todo](cases/dev/intro.md) - [加密解密 todo](cookbook/crypto.md)
- [日志](cases/dev/logs.md) - [时间日期](cookbook/date.md)
- [性能分析](cases/dev/profile.md) - [开发调试 todo](cookbook/dev/intro.md)
- [日志](cookbook/dev/logs.md)
- [性能分析](cookbook/dev/profile.md)
<!-- <!--
- [Rust区块链入门]() - [Rust区块链入门]()

@ -303,7 +303,7 @@ where
} }
``` ```
上面的缓存有一个很大的问题:只支持 `u32` 类型的值,若我们想要缓存 `String` 类型,显然就行不通了,因此需要将 `u32` 替换成泛型 `E`,该练习就留给读者自己完成,具体代码可以参考[这里](http://exercise.rs/functional-programming/closure.html) 上面的缓存有一个很大的问题:只支持 `u32` 类型的值,若我们想要缓存 `String` 类型,显然就行不通了,因此需要将 `u32` 替换成泛型 `E`,该练习就留给读者自己完成,具体代码可以参考[这里](https://practice.rs/functional-programing/cloure.html#closure-in-structs)
## 捕获作用域中的值 ## 捕获作用域中的值
@ -767,3 +767,6 @@ fn factory(x:i32) -> Box<dyn Fn(i32) -> i32> {
## 闭包的生命周期 ## 闭包的生命周期
这块儿内容在进阶生命周期章节中有讲,这里就不再赘述,读者可移步[此处](https://course.rs/advance/lifetime/advance.html#闭包函数的消除规则)进行回顾。 这块儿内容在进阶生命周期章节中有讲,这里就不再赘述,读者可移步[此处](https://course.rs/advance/lifetime/advance.html#闭包函数的消除规则)进行回顾。
{{#include ../../practice.md}}

@ -1,3 +0,0 @@
# 场景化用例
https://rust-lang-nursery.github.io/rust-cookbook/

@ -0,0 +1,155 @@
# 生成随机值
## 生成随机数
使用 [rand::thread_rng](https://docs.rs/rand/*/rand/fn.thread_rng.html) 可以获取一个随机数生成器 [rand::Rng](https://docs.rs/rand/0.8.5/rand/trait.Rng.html) ,该生成器需要在每个线程都初始化一个。
整数的随机分布范围等于类型的取值范围,但是浮点数只分布在 `[0, 1)` 区间内。
```rust,editable
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let n1: u8 = rng.gen();
let n2: u16 = rng.gen();
println!("Random u8: {}", n1);
println!("Random u16: {}", n2);
println!("Random u32: {}", rng.gen::<u32>());
println!("Random i32: {}", rng.gen::<i32>());
println!("Random float: {}", rng.gen::<f64>());
}
```
## 指定范围生成随机数
使用 [Rng::gen_range](https://rust-lang-nursery.github.io/rust-cookbook/algorithms/randomness.html) 生成 [0, 10) 区间内的随机数( 右开区间,不包括 `10` )。
```rust,editable
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
println!("Integer: {}", rng.gen_range(0..10));
println!("Float: {}", rng.gen_range(0.0..10.0));
}
```
[Uniform](https://docs.rs/rand/*/rand/distributions/uniform/struct.Uniform.html) 可以用于生成<ruby>均匀分布<rt>uniform distribution</rt></ruby>的随机数。当需要在同一个范围内重复生成随机数时,该方法虽然和之前的方法效果一样,但会更快一些。
```rust,editable
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;
}
}
}
```
## 使用指定分布来生成随机数
默认情况下,`rand` 包使用均匀分布来生成随机数,而 [rand_distr](https://docs.rs/rand_distr/*/rand_distr/index.html) 包提供了其它类型的分布方式。
首先,你需要获取想要使用的分布的实例,然后在 [rand::Rng](https://docs.rs/rand/*/rand/trait.Rng.html) 的帮助下使用 [Distribution::sample](https://docs.rs/rand/*/rand/distributions/trait.Distribution.html#tymethod.sample) 对该实例进行取样。
如果想要查询可用的分布列表,可以访问[这里](https://docs.rs/rand_distr/*/rand_distr/index.html),下面的示例中我们将使用 [Normal](https://docs.rs/rand_distr/0.4.3/rand_distr/struct.Normal.html) 分布:
```rust,editable
use rand_distr::{Distribution, Normal, NormalError};
use rand::thread_rng;
fn main() -> Result<(), NormalError> {
let mut rng = thread_rng();
let normal = Normal::new(2.0, 3.0)?;
let v = normal.sample(&mut rng);
println!("{} is from a N(2, 9) distribution", v);
Ok(())
}
```
## 在自定义类型中生成随机值
使用 [Distribution](https://docs.rs/rand/*/rand/distributions/trait.Distribution.html) 特征包裹我们的自定义类型,并为 [Standard](https://docs.rs/rand/*/rand/distributions/struct.Standard.html) 实现该特征,可以为自定义类型的指定字段生成随机数。
```rust,editable
use rand::Rng;
use rand::distributions::{Distribution, Standard};
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Distribution<Point> for Standard {
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();
// 生成一个随机的 Point
let rand_point: Point = rng.gen();
println!("Random Point: {:?}", rand_point);
// 通过类型暗示( hint )生成一个随机的元组
let rand_tuple = rng.gen::<(i32, bool, f64)>();
println!("Random tuple: {:?}", rand_tuple);
}
```
## 生成随机的字符串(A-Z, a-z, 0-9)
通过 [Alphanumeric](https://docs.rs/rand/0.8.5/rand/distributions/struct.Alphanumeric.html) 采样来生成随机的 ASCII 字符串,包含从 `A-Z, a-z, 0-9` 的字符。
```rust,editble
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);
}
```
## 生成随机的字符串( 用户指定 ASCII 字符 )
通过 [gen_string](https://docs.rs/rand/0.8.5/rand/trait.Rng.html#method.gen_range) 生成随机的 ASCII 字符串,包含用户指定的字符。
```rust,editable
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);
}
```

@ -0,0 +1,22 @@
# 场景化用例
对于开发者而言CookBook 是非常实用的,几乎每一门编程语言都是如此。原因无他:聪明的开发者大部分时间不是在复制粘贴就是在复制粘贴的路上。而 CookBook 恰恰为各种实用场景提供了可供直接复制粘贴的代码,例如文件操作、随机数生成、命令行解析等等,
> CookBook 的部分内容翻译自 [Rust CookBook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html),但是内容并不相同,因为我们对部分内容进行了整合,最重要的是增加了大量实用库和代码片段
## 这本书的读者
本书适合所有程度的 Rust 开发者使用:
- 新手用来熟悉生态和常用库
- 老手在写代码时,可以直接用来复制粘贴,大幅提升工作效率
毕竟咱不是在面试造飞机,谁脑袋中能记住文件操作的各种细节,对不?
## 怎么使用
Cookbook 中的代码都是完整的,换而言之,这些代码片段包含了 `fn main` 函数,可以直接运行,如果你是拷贝到自己的代码中,请注意拷贝相应的代码部分,而不是全盘复制。
同时,这些代码( 大部分 )支持在线编辑和运行,大家无需复制到 IDE 中即可进行把玩研究。

@ -0,0 +1,3 @@
## 课后习题
[https://practice.rs](https://practice.rs)
Loading…
Cancel
Save