随机数
关于随机数,Go语言标准库提供了两个包来实现,分别是math/rand和crypto/rand。
1. math/rand
原理:以一个真随机数(随机种子)作为初始条件,使用一定算法不停迭代产生随机数。
两个程序,如果设置相同的随机种子和相同的随机数范围,那么它们同样的调用次数,得到的随机数是一样的,所以这个包其实是一个伪随机数生成器。
下面以代码实践来说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import ( "fmt" "math/rand" ) func main() { rand.Seed(88) for i := 0; i < 10; i++ { n := rand.Intn(100) fmt.Println(n) } } |
这个程序,无论运行几次,其结果都是一样的:
也就是说,rand.Seed()函数设置随机种子为88的时候,第一次调用rand.Intn(100)得到的结果一定是97,第二次调用的结果一定是20,以此类推。
再来看看下面这个程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import ( "fmt" "math/rand" ) func main() { for i := 0; i < 10; i++ { rand.Seed(88) n := rand.Intn(100) fmt.Println(n) } } |
这个程序与上一个程序不同的是,在循环内部设置随机种子,也就是说循环中每次调用rand.Intn(100)的时候,都是设置随机种子为88以后的第一次调用,所以结果一定都是97:
也就是说,当随机种子确定的时候,产生的随机数序列其实确定的,是伪随机的,那么,要想得到完全随机的随机数序列,就要使用完全随机的随机种子,一般使用系统时间作为随机种子。
程序示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package main import ( "fmt" "math/rand" "time" ) func main() { rand.Seed(time.Now().UnixNano()) for i := 0; i < 10; i++ { n := rand.Intn(100) fmt.Println(n) } } |
因为每次调用程序,系统时间都不一样,所以产生的随机数列也就不相同了。
2. crypto/rand
原理:利用当前系统的一些特征,比如内存的使用量,文件的使用数量,不同类型的进程数量等等来进行计算产生随机数,因此产生重复随机数的概率很低。
这个包产生的随机数更安全,加解密一般就使用这个包来产生随机数。
程序示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main import ( "crypto/rand" "fmt" "math/big" "os" ) func main() { b := new(big.Int).SetInt64(int64(100)) for i := 0; i < 10; i++ { n, err := rand.Int(rand.Reader, b) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println(n) } } |
注:crypto/rand产生随机数的效率比math/rand要慢很多。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)