go math/rand包詳解
go math/rand
package rand
import "math/rand"
rand包實現了偽隨機數生成器。
隨機數從資源生成。包水平的函式都使用的預設的公共資源。該資源會在程式每次執行時都產生確定的序列。如果需要每次執行產生不同的序列,應使用Seed
函式進行初始化。預設資源可以安全的用於多go執行緒併發。
在go中生成隨機數需要一個結構體例項 Rand
,要構建這個結構體需要一些引數;為了便捷,go已經在math/rand
包中定義好了一個Rand
結構體例項,只需要呼叫Rand
的一些方法就可以生成各種隨機數來。下面簡單認識一下Rand
結構體:
type Rand struct { src Source s64 Source64 // 如果src為空,則為64 // readVal包含用於位元組的63位整數的remainer,在最近的讀取呼叫期間生成。 // 它被儲存,以便下一個讀呼叫可以從上一個讀呼叫結束的地方開始。 readVal int64 // readPos表示仍然有效的readVal的低位位元組數。 readPos int8 }
簡單示例:
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.Seed 設定隨機數種子
func (r *Rand) Seed(seed int64)
seed
來初始化生成器到一個確定的狀態。
修改後的程式碼:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano()) // 取納秒時間戳,可以保證每次的隨機數種子都不同
fmt.Println(rand.Int())
fmt.Println(rand.Int31())
fmt.Println(rand.Intn(5))
}
程式碼多次執行,就會發現每次結果是不一樣的
7684945739848266880 1210528256 4 ------------------- 4700552700982711365 1927716820 4
自定義生成Rand結構體,設定隨機數種子
除了上面生成偽隨機數的方法,我們還可以自定義生成Rand
結構體,本質上與Rand
提供好的結構體沒有太大區別,下面簡單介紹下自己宣告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(rand.Int())
fmt.Println(rand.Int31())
fmt.Println(rand.Intn(5))
}
這兩種方法本質上沒有區別,NewSource()
方法等價於前面的rand.Seed()方法
,都是用來設定隨機種子。
其它生成隨機數的方法
Rand
生成隨機數當然不只這三個方法,還有其它生成隨機數的方法
func (r *Rand) Int63() int64
返回一個int64型別的非負的63位偽隨機數。
func (r *Rand) Uint32() uint32
返回一個uint32型別的非負的32位偽隨機數。
func Int31n(n int32) int32
返回一個取值範圍在[0,n)的偽隨機int32值,如果n<=0會panic。
func Int63n(n int64) int64
返回一個取值範圍在[0, n)的偽隨機int64值,如果n<=0會panic。
func (r *Rand) Float32() float32
返回一個取值範圍在[0.0, 1.0)的偽隨機float32值。
func (r *Rand) Float64() float64
返回一個取值範圍在[0.0, 1.0)的偽隨機float64值。
func (r *Rand) Perm(n int) []int
返回一個有n個元素的,[0,n)範圍內整數的偽隨機排列的切片。