需要手动调用rand.Seed吗?

huangapple go评论106阅读模式
英文:

Is it necessary to call rand.Seed manually?

问题

在Go语言中,如果你想要生成不同的随机数序列,你需要在调用rand.Intn(100)之前调用rand.Seed(n)来设置随机数种子。种子值n可以是任意整数,通常使用当前时间的纳秒数作为种子值,例如rand.Seed(time.Now().UnixNano())。这样做可以确保每次运行程序时都会生成不同的随机数序列。所以,在你的代码中,你需要在每次调用rand.Intn(100)之前调用rand.Seed(n)来确保每次运行时都会生成不同的随机数。

英文:

I want to know do we have to call rand.Seed(n) manually in Go?
I have a code that looks like this:

import (
	"fmt"
	"math/rand"
)

func main() {
	fmt.Println(rand.Intn(100))
	fmt.Println(rand.Intn(100))
	fmt.Println(rand.Intn(100))
}

Everytime I run this code, each line prints different numbers than the others.
So do I need to call rand.Seed(n) each time before calling rand.Intn(100)?

答案1

得分: 6

在 Go 1.20 之前,全局共享的随机数源在内部被初始化为 1,因此每次运行应用程序都会产生相同的伪随机序列。

从 Go 1.20 开始,不再需要调用 rand.Seed()发布说明

> math/rand 包现在会自动使用随机值对全局随机数生成器(由 Float64Int 等顶级函数使用)进行初始化,而顶级的 Seed 函数已被弃用。 需要可重现的随机数序列的程序应该优先分配自己的随机源,使用 rand.New(rand.NewSource(seed))
>
> 需要早期一致的全局初始化行为的程序可以在环境中设置 GODEBUG=randautoseed=0
>
> 顶级的 Read 函数已被弃用。在几乎所有情况下,更适合使用 crypto/rand.Read

rand.Seed() 的文档中也有这个弃用声明

> 弃用:调用 Seed,然后期望从全局随机源(使用 Int 等函数)获得特定结果序列的程序,在依赖项更改其从全局随机源中消耗的量时可能会出现问题。为了避免这种问题,需要特定结果序列的程序应该使用 NewRand(NewSource(seed)) 来获取其他包无法访问的随机生成器。

英文:

Prior to Go 1.20, the global, shared Source was seeded to 1 internally, so each run of the appliation would produce the same pseudo-random sequences.

Calling rand.Seed() is not needed starting from Go 1.20. Release notes:

> The math/rand package now automatically seeds the global random number generator (used by top-level functions like Float64 and Int) with a random value, and the top-level Seed function has been deprecated. Programs that need a reproducible sequence of random numbers should prefer to allocate their own random source, using rand.New(rand.NewSource(seed)).
>
> Programs that need the earlier consistent global seeding behavior can set GODEBUG=randautoseed=0 in their environment.
>
> The top-level Read function has been deprecated. In almost all cases, crypto/rand.Read is more appropriate.

rand.Seed() also has this DEPRICATION in its doc:

> Deprecated: Programs that call Seed and then expect a specific sequence of results from the global random source (using functions such as Int) can be broken when a dependency changes how much it consumes from the global random source. To avoid such breakages, programs that need a specific result sequence should use NewRand(NewSource(seed)) to obtain a random generator that other packages cannot access.

答案2

得分: 1

你需要创建一个源代码:

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	wdRand := rand.New(rand.NewSource(42))
	fmt.Println(wdRand.Intn(100))
	fmt.Println(wdRand.Intn(100))
	fmt.Println(wdRand.Intn(100))
}

现在每次调用这段代码,结果都会变得相同。

你可以在这个链接上运行代码并查看结果:https://go.dev/play/p/Sp0Wfx0Bkbb

英文:

You have to create a Source:

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	wdRand := rand.New(rand.NewSource(42))
	fmt.Println(wdRand.Intn(100))
	fmt.Println(wdRand.Intn(100))
	fmt.Println(wdRand.Intn(100))
}

https://go.dev/play/p/Sp0Wfx0Bkbb

Now everytime you call the code, the results become identical.

huangapple
  • 本文由 发表于 2023年7月12日 16:20:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76668508.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定