我试图准确理解为什么,当从外部函数调用时,我的时间播种随机数生成器返回相同数字的序列.
问题的最小工作示例:
package main
import (
"fmt"
"math/rand"
"time"
)
//Generates random int as function of range
func getRand(Range int) int {
s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
return r1.Intn(Range)
}
//Print 100 random ints between 0 and 100
func main() {
for i := 0; i < 100; i++ {
fmt.Print(getRand(100), ", ")
}
}
Run Code Online (Sandbox Code Playgroud)
这个的输出是
Out[1]: 40, 40, 40, 40, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 47,
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
47,47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99,
Run Code Online (Sandbox Code Playgroud)
我想知道为什么这会发生在我自己的教育上.我也愿意接受解决方案的建议.
细节:我需要在我的代码的许多外部函数中调用随机数,但是,就像这个MWE一样,当在除main之外的函数中播种时,它们会重复返回相同的数字.另外,我需要动态更新范围,因此不能选择生成先验列表.我宁愿不必在main()中生成数字并将它们传递给每个函数 - 范围是在这些内部计算的,这会使事情复杂化
这是因为time.Time有一个粒度(1纳秒)就像你的系统时钟(甚至可能是几毫秒 - 取决于很多东西),如果你time.Now()在这些粒度中的较大者内多次调用,那么返回的机会很time.Time可能是相同,意味着它的Time.UnixNano()方法将返回相同的纳秒(相同的数字).
如果你使用与种子相同的数字,随机数生成器应该返回相同的数字.
您只需要在应用启动时为RNG播种一次,而不是在每次使用之前播种.您可以使用包init()函数,或在变量声明中使用:
var r = rand.New(rand.NewSource(time.Now().UnixNano()))
//Generates random int as function of range
func getRand(Range int) int {
return r.Intn(Range)
}
//Print 100 random ints between 0 and 100
func main() {
for i := 0; i < 100; i++ {
fmt.Print(getRand(100), ", ")
}
}
Run Code Online (Sandbox Code Playgroud)
示例输出(在Go Playground上尝试):
0,28,27,62,63,89,24,27,88,84,82,55,49,35,2,32,84,58,78,28,26,58,30,28,74, 6,39,24,40,47,49,39,61,62,67,7,94,87,37,99,90,80,93,83,27,69,25,45,99,12, 44,39,34,86,18,42,76,40,44,12,70,3,70,99,57,43,90,65,97,64,68,60,65,56,3, 81,54,56,43,57,92,93,54,92,9,66,16,72,29,12,77,87,55,42,87,41,94,53,23,64,
这里要注意的一件事是:rand.NewSource()返回一个对于并发使用不安全的源.如果需要getRand()从多个goroutine 调用,则需要同步访问r,或rand.Rand在每个goroutine中使用单独的.
| 归档时间: |
|
| 查看次数: |
338 次 |
| 最近记录: |