Golang中math/rand的算法原理是什么?

Golang中math/rand的算法原理是什么? 有人知道 Go 的 math/rand 使用了哪种算法吗?我查看了源代码并搜索了相关信息,但毫无头绪。资料显示它仅采用了贝尔实验室 Plan 9 项目中的均匀分布实现。这个链接 https://github.com/seehuhn/mt19937 提到 math/rand 的结果与梅森旋转算法相同。

能否有人提供 math/rand 背后算法的参考资料?

提前感谢。

7 回复

我同意,但从学习编程的普遍实践来看,这在表面上确实容易让人困惑。编程新手期望随机就是随机的,哈哈。

更多关于Golang中math/rand的算法原理是什么?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


CliffordBernard:

此外,关于 Rand 的问题在于,如果使用相同的种子,结果总是会相同。

为什么这是个问题?

我认为这是预期行为,几乎所有的伪随机数生成算法都是这样工作的……

感谢您的回复。

我也发现了一些有趣的帖子。 一个很好的图形说明帖子:https://appliedgo.net/random/ 以及 rngSource https://golang.org/src/math/rand/rng.go 但我仍然不了解其背后的数学理论(通过均匀分布生成的数字)。

非常感谢Saito先生,这非常有帮助。

我查阅了随机数生成器列表 关于LFG没有任何评论。 我想了解LFG和梅森旋转算法的比较。 因为我计划使用梅森旋转算法(MT)或更好的算法。 有人知道MT是否比LFG更好吗?

该算法可在以下链接中找到:

https://golang.org/src/math/rand/rand.go?s=10571:10591#L319

此外,Rand 的问题在于如果使用相同的种子,结果总是相同的。下面是一个使用时间生成 Rand 的 Rand 的示例。GoPlay.Space 无法正确提供时间;但是,如果您将其放入 IDE 中,它可以正常工作。希望这能有所帮助。祝你好运。

Rand 的 Rand 示例:
https://goplay.space/#fd8MuhFMICf

延迟斐波那契生成器

"如果我没再次理解错的话,这个生成器属于ALFG(加法延迟斐波那契生成器,这是维基百科的称呼)。Knuth在《计算机程序设计艺术》第二卷的3.2.2节中描述了该算法(围绕方程7展开)。维基百科和Knuth都指出参数组合607和273是可行的配置,其周期长度为2^(e-1) * (2^607-1),其中e表示随机数的位长。

实际上我找到了一些研究其特性的文献,目前看来这是个不错的随机数生成器,但似乎仍缺乏数学理论支撑,而且如果初始化种子不当很容易出现问题。"

https://groups.google.com/forum/m/#!topic/golang-nuts/RZ1G3_cxMcM

在 Go 语言中,math/rand 包使用的算法是一个线性同余生成器(Linear Congruential Generator, LCG),具体实现基于贝尔实验室 Plan 9 项目中的均匀分布伪随机数生成器。该算法通过一个简单的递推公式生成伪随机序列,公式为:

[ X_{n+1} = (a \cdot X_n + c) \mod m ]

其中,(a)、(c) 和 (m) 是常数,(X_n) 是当前状态。在 Go 的实现中,这些参数被设定为固定值,以确保跨平台的一致性。源代码中,rng 函数和相关方法封装了该逻辑。

关于您提到的梅森旋转算法(Mersenne Twister),Go 的 math/rand 默认并不使用它。梅森旋转算法通常用于更高质量的随机性需求,例如在 crypto/rand 包中或第三方库中实现。您提供的 GitHub 链接可能是在比较不同算法的输出,但 Go 的标准库 math/rand 核心是 LCG。

以下是一个简单示例,展示如何使用 math/rand 生成随机数,并说明其基本用法:

package main

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

func main() {
	// 使用当前时间作为种子,以确保每次运行结果不同
	rand.Seed(time.Now().UnixNano())
	
	// 生成一个介于 0 和 99 之间的随机整数
	randomNum := rand.Intn(100)
	fmt.Printf("随机数: %d\n", randomNum)
	
	// 生成一个介于 0.0 和 1.0 之间的随机浮点数
	randomFloat := rand.Float64()
	fmt.Printf("随机浮点数: %f\n", randomFloat)
}

如果您需要更高质量的随机数(如密码学安全),建议使用 crypto/rand 包。对于 math/rand 的算法细节,可以参考 Go 官方源代码中的 src/math/rand/rng.go 文件,其中定义了 LCG 的具体实现。

回到顶部