golang-标准库(math/rand)

rand包是go提供用来产生各种各样随机数的包,本文对这些产生随机数的方法做一下介绍。注意:rand生成的数值虽然说是随机数,但它其实是伪随机数,关于为什么是伪随机数,而不是真正的随机数,本文不做详细讲解,因为我也不是太清楚,只是提出这一点;简单说一下我的理解:真正的随机数是无规则可循的,就像抛硬币,正反面是真正随机的,这是一个真正的随机案例。计算机底层生成一个数值,究其根源它也是程序员们根据某种算法得到的数值,而是要是人为操控的计算就一定有规律可循,只是这个规律不是肉眼可见的。所以说是伪随机数。

在go中生成随机数需要一个结构体实例 Rand ,要构建这个结构体需要一些参数;为了便捷,go已经在math/rand包中定义好了一个Rand结构体实例,只需要调用Rand的一些方法就可以生成各种随机数来。下面简单认识一下Rand结构体:

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。

下面再看上面方法的简单示例:

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	// 直接调用rand的方法生成伪随机int值
	fmt.Println(rand.Int())
	fmt.Println(rand.Int31())
	fmt.Println(rand.Intn(5))
}

上面的代码我的运行结果是:

5577006791947779410
2019727887
2

但是当把代码运行多次发现,结果都是一样的。不管怎么运行代码,产生的结果都是这三个数,结果不会变。为什么?这是因为我们还没有设置随机数种子的原因。

Rand产生的伪随机数,是根据一个种子值来生成的,上面的代码,我没有设置这个种子,所以每次获得的值都是一样的。下面来看怎么设置这个种子:

func (r *Rand) Seed(seed int64) => 使用给定的seed来初始化生成器到一个确定的状态。这就是设置随机种子。

下面看修改后的代码:


func main() {
	// 直接调用rand的方法生成伪随机int值
	rand.Seed(time.Now().Unix()) // 设置种子,我们以当前时间的秒;当然也可以用毫秒,微秒等
	fmt.Println(rand.Int())
	fmt.Println(rand.Int31())
	fmt.Println(rand.Intn(5))
}

上面的代码,多次运行,就会发现,结果是不一样的了。

Rand不只这三个方法,还有生成其它随机数的方法,下面看列表:

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提供好的结构体没有太大区别,下面简单介绍一些i自己声明Rand机构体,来生成伪随机数:

先看二个方法:

func NewSource(seed int64) Source =》使用给定的种子创建一个伪随机资源。
func New(src Source) *Rand =》返回一个使用src随机源生成一个Rand。

下面看代码示例:

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()方法,都是用来设置随机种子。

到此,math/rand包就介绍完了。

你可能感兴趣的:(go,golang标准库)