golang學習筆記 ---rand


在Golang中,有兩個包提供了rand,分別為 "math/rand" 和 "crypto/rand",  對應兩種應用場景。

  • "math/rand" 包實現了偽隨機數生成器。也就是生成 整形和浮點型。 該包中根據生成偽隨機數是是否有種子(可以理解為初始化偽隨機數),可以分為兩類:
    • 有種子。通常以時鍾,輸入輸出等特殊節點作為參數,初始化。該類型生成的隨機數相比無種子時重復概率較低。
    • 無種子。可以理解為此時種子為1, Seek(1)

golang 隨機數有一個很有趣的地方,如果我們不自行定義隨機數種子的話,每次生成的隨機數都是一樣的。golang 在默認隨機的時候,固定以數字 1 作為種子。既然種子都固定了的話,那每次執行的結果當然是一樣的。比如 第二個for 循環,打印 10 個隨機數,每次運行結果是一模一樣的。 

要解決這個問題,就需要以時間作為隨機數種子。如第一個for循環:

package main

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

func main() {
      //以時間為隨機種子 for i := 0; i < 10; i++ r := rand.New(rand.NewSource(time.Now().UnixNano())) fmt.Printf("%d ", r.Int31()) } fmt.Println(" ")
    //無種子,其實是固定以1為種子 for i := 0; i < 10; i++ { fmt.Printf("%d ", rand.Int31()) } }

  輸出:

第一次運行結果

276310213 276310213 276310213 939632684 939632684 939632684 939632684 939632684 939632684 939632684

1298498081 2019727887 1427131847 939984059 911902081 1474941318 140954425 336122540 208240456 646203300

 

第二次運行結果

1101837366 1101837366 1101837366 1101837366 1101837366 1101837366 1101837366 1101837366 1101837366 1101837366

1298498081 2019727887 1427131847 939984059 911902081 1474941318 140954425 336122540 208240456 646203300

 

第三次運行結果

483465292 483465292 483465292 483465292 1406725908 1406725908 1406725908 1406725908 1406725908 1406725908

1298498081 2019727887 1427131847 939984059 911902081 1474941318 140954425 336122540 208240456 646203300

 

常用的方法有:(以有種子的為例,無種子的直接通過 rand 調用對應的方法)

1> 按類型隨機類:
func (r *Rand) Int() int
func (r *Rand) Int31() int32
func (r *Rand) Int63() int64
func (r *Rand) Uint32() uint32
func (r *Rand) Float32() float32  // 返回一個取值范圍在[0.0, 1.0)的偽隨機float32值
func (r *Rand) Float64() float64  // 返回一個取值范圍在[0.0, 1.0)的偽隨機float64值

2>指定隨機范圍類:
func (r *Rand) Intn(n int) int
func (r *Rand) Int31n(n int32) int32
func (r *Rand) Int63n(n int64) int64

 

拓展:對於需要隨機指定位數的,當位數不夠是,可以通過前邊補0達到長度一致,如

package main
import (
    "fmt"
    "math/rand"
)
func main() {
    // 隨機產生6位長度偽隨機數
    for i := 0; i < 10; i++ {
        fmt.Printf("%.6d ", rand.Int31()%1000000)
    }
}

  輸出

498081 727887 131847 984059 902081 941318 954425 122540 240456 203300

 

package main
import (
    "fmt"
    "math/rand"
    "time"
)
func init() {
    //以時間作為初始化種子
    rand.Seed(time.Now().UnixNano())
}
func main() {
    a := rand.Int()
    fmt.Println(a)
    b := rand.Intn(100)
    fmt.Println(b)
    c := rand.Float32()
    fmt.Println(c)
}

  輸出:

1910927962
45
0.9863281

  

 

”crypto/rand“ 包實現了用於加解密的更安全的隨機數生成器:該包中常用的是 func Read(b []byte) (n int, err error) 這個方法, 將隨機的byte值填充到b 數組中,以供b使用。示例如下:

package main

import (
	"crypto/rand"
	"fmt"
)

func main() {
	b := make([]byte, 20)
	fmt.Println(b) //

	_, err := rand.Read(b)
	if err != nil {
		fmt.Println(err.Error())
	}

	fmt.Println(b)
}

幾點注意項:

1、如果不使用rand.Seed(seed int64),每次運行,得到的隨機數會一樣,程序不停止,一直獲取的隨機數是不一樣的;

2、每次運行時rand.Seed(seed int64),seed的值要不一樣,這樣生成的隨機數才會和上次運行時生成的隨機數不一樣;

3、rand.Intn(n int)得到的隨機數int i,0 <= i < n。



  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM