标签: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