首页 > 其他分享 >(转)golang-标准库(math/rand)

(转)golang-标准库(math/rand)

时间:2023-02-06 17:34:32浏览次数:30  
标签:rand 随机数 Rand int golang 随机 func math

原文:https://itpika.com/2019/07/09/go/library-math-rand/

rand包是go提供用来产生各种各样随机数的包,本文对这些产生随机数的方法做一下介绍。注意:rand生成的数值虽然说是随机数,但它其实是伪随机数,关于为什么是伪随机数,而不是真正的随机数,本文不做详细讲解,因为我也不是太清楚,只是提出这一点;简单说一下我的理解:真正的随机数是无规则可循的,就像抛硬币,正反面是真正随机的,这是一个真正的随机案例。计算机底层生成一个数值,究其根源它也是程序员们根据某种算法得到的数值,而是要是人为操控的计算就一定有规律可循,只是这个规律不是肉眼可见的。所以说是伪随机数。 在go中生成随机数需要一个结构体实例 Rand ,要构建这个结构体需要一些参数;为了便捷,go已经在math/rand包中定义好了一个Rand结构体实例,只需要调用Rand的一些方法就可以生成各种随机数来。下面简单认识一下Rand结构体:    
1
2
3
4
5
6
7
type Rand struct {
// 内含隐藏或非导出字段
}
// Rand实现的几个方法
func (r *Rand) Int() int =》 返回一个非负的伪随机int值。
func (r *Rand) Int31() int32 =》 返回一个int32类型的非负的31位伪随机数。
func (r *Rand) Intn(n int) int =》 返回一个取值范围在[0,n)的伪随机int值,如果n<=0会panic。
 下面再看上面方法的简单示例:    
1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
"math/rand"
)

func main() {
// 直接调用rand的方法生成伪随机int值
fmt.Println(rand.Int()) // 5577006791947779410
fmt.Println(rand.Int31()) // 2019727887
fmt.Println(rand.Intn(5)) // 2
}
 但是当把代码运行多次发现,结果都是一样的。不管怎么运行代码,产生的结果都是这三个数,结果不会变。为什么?这是因为我们还没有设置随机数种子的原因。 Rand产生的伪随机数,是根据一个种子值来生成的,上面的代码,我没有设置这个种子,所以每次获得的值都是一样的。下面来看怎么设置这个种子:
func (r *Rand) Seed(seed int64) => 使用给定的seed来初始化生成器到一个确定的状态。这就是设置随机种子。  下面看修改后的代码:    
1
2
3
4
5
6
7
func main() {
// 直接调用rand的方法生成伪随机int值
rand.Seed(time.Now().Unix()) // 设置种子,我们以当前时间的秒;当然也可以用毫秒,微秒等
fmt.Println(rand.Int())
fmt.Println(rand.Int31())
fmt.Println(rand.Intn(5))
}
上面的代码,多次运行,就会发现,结果是不一样的了。
Rand不只这三个方法,还有生成其它随机数的方法,下面看列表:    
1
2
3
4
5
6
7
8
9
func Int63() int64 =》 返回一个int64类型的非负的63位伪随机数。
func Uint32() uint32 =》返回一个uint32类型的非负的32位伪随机数。
func Uint64() uint64 =》返回一个uint64类型的非负的32位伪随机数。
func Int31n(n int32) int32 =》返回一个取值范围在[0,n)的伪随机int32值,如果n<=0会panic。
func Int63n(n int64) int64 =》返回一个取值范围在[0, n)的伪随机int64值,如果n<=0会panic。
func Float32() float32 =》返回一个取值范围在[0.0, 1.0)的伪随机float32值。
func Float64() float64 =》返回一个取值范围在[0.0, 1.0)的伪随机float64值。
func Perm(n int) []int =》返回一个有n个元素的,[0,n)范围内整数的伪随机的切片。
func Read(p []byte) (n int, err error) => 生成len(p)个伪随机数,伪随机数的范围为0-255;并将伪随机数存入p,返回len(p)和可能发生的错误。
这些函数大都见名知意,比较简单,就是获取各种类型的伪随机数(Int),与之对应的还有获取某种类型的某个范围的伪随机数(Intn)。最后二个方法属于封装的方法,适用于一些特定的场景。

除此上面生成伪随机数的方法,我们还可以字节定义生成Rand机构体,不过本质上与rand提供好的结构体没有太大区别,下面简单介绍一些自己声明Rand机构体,来生成伪随机数:
先看二个方法:    
1
2
func NewSource(seed int64) Source =》使用给定的种子创建一个伪随机资源。
func New(src Source) *Rand =》返回一个使用src随机源生成一个Rand。
 下面看代码示例:    
1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
"math/rand"
"time"
)

func main() {
source := rand.NewSource(time.Now().UnixNano()) // 使用当前的纳秒生成一个随机源,也就是随机种子
ran := rand.New(source) // 生成一个rand
fmt.Println(ran.Int()) // 获取随机数
}
这两种方法本质上没有区别,NewSource()方法就等价于前面的rand.Seed()方法,都是用来设置随机种子。

标签:rand,随机数,Rand,int,golang,随机,func,math
From: https://www.cnblogs.com/liujiacai/p/17096095.html

相关文章