<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
亂數從資源生成。包水平的函數都使用的預設的公共資源。
該資源會在程式每次執行時都產生確定的序列。如果需要每次執行產生不同的序列,應使用Seed函數進行初始化。預設資源可以安全的用於多go程並行。
關於種子seed
程式啟動的時候,種子的初始值是一樣的,也就是說亂數是一樣的,什麼意思呢?
package main import ( "fmt" "math/rand" ) func main(){ data := rand.Int63n(100) fmt.Println(data) }
每次執行go run main.go
列印的都是 10
如果我們播放種子
package main import ( "fmt" "math/rand" "time" ) func main(){ rand.Seed(time.Now().Unix()) // unix 時間戳,秒 data := rand.Int63n(100) fmt.Println(data) }
這樣每次執行go run main.go
列印的結果就不一樣,但是,根據亂數的特性,如果兩次執行的時間戳是在同一秒,那麼列印的結果是相同的。
以上的亂數相同的情況是發生在程式啟動的時候,如果程式啟動後,每次生成亂數會怎樣呢?
package main import ( "fmt" "math/rand" ) func main(){ for i := 0; i<5; i++ { data := rand.Int63n(100) fmt.Println(data) } }
執行 go run main.go
列印
10
51
21
51
37再次執行 go run main.go
列印
10
51
21
51
37
可見每次啟動的結果是一樣的;但是程式啟動後,每次的亂數都不盡相同,是隨機的。
如果再加上種子呢?
package main import ( "fmt" "math/rand" "time" ) func main(){ for i := 0; i<5; i++ { rand.Seed(time.Now().Unix()) // unix 時間戳,秒 data := rand.Int63n(100) fmt.Println(data) } }
執行 go run main.go
列印
86
86
86
86
86再次執行 go run main.go
列印
72
72
72
72
72
每次啟動程式,因為種子不一樣,所以亂數不一樣;但是程式啟動後,每次也都是播放種子,秒級時間戳,如果時間戳一樣,就導致種子一樣,生成的亂數就一樣,所以五次的亂數是一樣的。
通過上面的例子。可以知道,播放種子不是必須的,除非要求每次啟動程式的時候亂數不一樣。
並且,要設定種子的情況下,應該放在整個程式啟動的時候,而且只需要設定一次即可。修改上面的例子:
package main import ( "fmt" "math/rand" "time" ) func main(){ rand.Seed(time.Now().UnixNano()) // 納秒時間戳 for i := 0; i<5; i++ { data := rand.Int63n(100) fmt.Println(data) } }
執行 go run main.go
列印
3
49
46
83
25再次執行 go run main.go
列印
39
3
14
42
65
這次就是理想的結果了。使用納秒時間戳基本就沒問題了,因為我們的程式幾乎不會在1納秒時間內多次啟動的。
下面來講講rand包的具體用法
rand 包提供了兩塊的內容,一塊是基於 Rand 結構體及其方法;另一塊是基於 Rand 結構體再封裝的可直接呼叫的方法 rand.xxx,檢視原始碼就知道它們是同樣的功能。
所以,生成亂數有兩種方式
rander := rand.New(rand.NewSource(time.Now().UnixNano())) n1 := rander.Intn(100) rand.Seed(time.Now().UnixNano()) n2 := rand.Intn(100)
使用第一種方法,將 rander 作為包的全域性變數,這樣就只會設定一次種子。
var Rander = rand.New(rand.NewSource(time.Now().UnixNano()))
隨機整數
func (r *Rand) Int() int func (r *Rand) Int31() int32 func (r *Rand) Int63() int64 func (r *Rand) Uint32() uint32 func (r *Rand) Uint64() uint64 func (r *Rand) Intn(n int) int func (r *Rand) Int31n(n int32) int32 func (r *Rand) Int63n(n int64) int64
Int, Int31, Int63 生成的數都太大,一般使用 Intn, Int31n, Int63n。得到的範圍 [0, n),想要得到 [0, n],就要使用 Intn(n + 1),想要得到 [10, 100] 的亂數,就要使用 Intn(91) + 10。
隨機浮點數
func (r *Rand) Float32() float32 func (r *Rand) Float64() float64
得到 [0, 1) 之間的浮點數,32單精度,64雙精度。
基於正態分佈的隨機浮點數
func (r *Rand) NormFloat64() float64
基於指數分佈的隨機浮點數
func (r *Rand) ExpFloat64() float64
隨機序列
func (r *Rand) Perm(n int) []int
返回一個有n個元素的,[0,n)範圍內整數的偽隨機排列的切片。
Rander.Perm(10) // [1 8 0 4 7 6 3 2 9 5]
總結:
package main import ( "fmt" "math/rand" "strings" "time" ) func main() { s := RandString(10) fmt.Println(s) } var Rander = rand.New(rand.NewSource(time.Now().UnixNano())) const letterString = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" const numLetterString = "0123456789" // 隨機生成字串 func RandStr(n int, letter string) string { str := []byte(letter) res := "" for i := 0; i < n; i++ { res += fmt.Sprintf("%c", str[Rander.Intn(strings.Count(letter, "") - 1)]) } return res } func RandNumStr(n int) string { return RandStr(n, numLetterString) } func RandString(n int) string { return RandStr(n, letterString) } func RandOrder(n int) string { return time.Now().Format("20060102150405") + RandNumStr(n) } // 包含min, max func RandNum(min , max int) int { return Rander.Intn(max - min + 1) + min }
實現了用於加解密的更安全的亂數生成器。
變數 var Reader io.Reader
是一個全域性、共用的密碼用強隨機生成器。在Unix型別系統中,會從/dev/urandom讀取;而windows中會呼叫RtlGenRandom API。
提供的方法
1、返回一個基於[0, max)的亂數
// Int returns a uniform random value in [0, max). It panics if max <= 0. func Int(rand io.Reader, max *big.Int) (n *big.Int, err error)
範例
r, err := rand.Int(rand.Reader, big.NewInt(100)) fmt.Println(r.Int64(), err)
2、根據指定的位數bits,返回一個數,大概率是素數,(不知道這個函數是幹嘛用的)
// Prime returns a number, p, of the given size, such that p is prime // with high probability. // Prime will return error for any error returned by rand.Read or if bits < 2. func Prime(rand io.Reader, bits int) (p *big.Int, err error)
範例
p, err := rand.Prime(rand.Reader, 8) fmt.Println(p.Int64(), err)
8個二進位制位的最大值為255,此處會隨機返回小於255的素數。
3、生成隨機的二進位制序列
// Read is a helper function that calls Reader.Read using io.ReadFull. // On return, n == len(b) if and only if err == nil. func Read(b []byte) (n int, err error) { return io.ReadFull(Reader, b) }
比如,隨機生成16個位元組的資料
var b [16]byte n, err := rand.Read(b[:]) fmt.Println(n, err) fmt.Println(b)
返回值
16 <nil>
[94 184 113 36 224 18 239 52 69 242 14 84 174 113 125 15]
我們可以將其轉換成16進位制數,也就是32位元
buf := make([]byte, 32) hex.Encode(buf, b[:]) fmt.Println(string(buf))
得到
5eb87124e012ef3445f20e54ae717d0f
通過這個方法可以生成隨機的字串。
到此這篇關於golang中亂數rand的使用的文章就介紹到這了,更多相關golang亂數rand內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45