網站首頁 編程語言 正文
1、math/rand
隨機數從資源生成。包水平的函數都使用的默認的公共資源。
該資源會在程序每次運行時都產生確定的序列。如果需要每次運行產生不同的序列,應使用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 }
2、crypto/rand
實現了用于加解密的更安全的隨機數生成器。
變量 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
通過這個方法可以生成隨機的字符串。
原文鏈接:https://blog.csdn.net/raoxiaoya/article/details/109101145
相關推薦
- 2022-07-10 詳解BlockingQueue阻塞隊列的使用
- 2022-07-04 Python+Pillow+Pytesseract實現驗證碼識別_python
- 2021-12-05 判斷網頁時瀏覽器打開還是釘釘打開
- 2022-08-31 C語言數據結構之單鏈表與雙鏈表的增刪改查操作實現_C 語言
- 2024-01-12 間隙鎖(Gap Lock)
- 2022-05-19 聊聊Python代碼中if?__name__?==?‘__main__‘的作用是什么_python
- 2022-11-21 C#基礎知識之字符串和正則表達式_C#教程
- 2022-09-16 Pandas篩選DataFrame含有空值的數據行的實現_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支