golang rand.Int(). Why every time same values?

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

golang rand.Int(). Why every time same values?

问题

我有一段代码:

package main

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

func main() {
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
	fmt.Println(strconv.Itoa(rand.Int()))
}

当我运行它(go run code.go)时,每次都得到相同的值:

5577006791947779410
8674665223082153551
6129484611666145821
4037200794235010051
3916589616287113937
6334824724549167320
605394647632969758
1443635317331776148
894385949183117216
2775422040480279449
4751997750760398084
7504504064263669287
1976235410884491574
3510942875414458836

第二次尝试:

package main

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

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

同样的行为。每次都是:

81
87
47
59
81
18
25

这是一个C语言的方式:

golang rand.Int(). Why every time same values?

英文:

I have a code:

package main

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

func main() {
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
}

When I run it (go run code.go), I get every time same values:

5577006791947779410
8674665223082153551
6129484611666145821
4037200794235010051
3916589616287113937
6334824724549167320
605394647632969758
1443635317331776148
894385949183117216
2775422040480279449
4751997750760398084
7504504064263669287
1976235410884491574
3510942875414458836

Second try:

package main

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

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

Same behaviour. Every time's

81
87
47
59
81
18
25

<s>Is this a joke? Why it happens?
Here is no description about non-random same result.
I can see only pseudo-random term without explanation what that means.

<sup>Looks like even bash is more logical and stable...</sup>
</s>

This is a C way

golang rand.Int(). Why every time same values?

答案1

得分: 14

你需要对其进行种子初始化。在文档中明确说明了这一点。

> 随机数是由源生成的。顶级函数(如Float64和Int)使用一个默认的共享源,每次运行程序时都会产生一个确定性序列的值。如果需要每次运行时都有不同的行为,可以使用Seed函数来初始化默认的源。

通常情况下,可以使用以下代码进行种子初始化:

rand.Seed(time.Now().UnixNano())
英文:

You need to seed it. It says right in the docs

> Random numbers are generated by a Source. Top-level functions, such as Float64 and Int, use a default shared Source that produces a deterministic sequence of values each time a program is run. Use the Seed function to initialize the default Source if different behavior is required for each run.

Generally

rand.Seed(time.Now().UnixNano())

答案2

得分: 6

在使用生成器之前,您似乎没有调用Seed函数对math/rand进行种子初始化。

如果没有调用Seed函数,生成器的行为就像通过Seed(1)进行了种子初始化一样。这并不是一个玩笑 - 实际上,在许多情况下,确定性和可重复性的伪随机数生成是可取的。

如果需要不同的随机数,请使用不同的种子值进行初始化,例如time.Now().UnixNano()

英文:

You don't appear to have called Seed for math/rand before using the generator.

If Seed is not called, the generator behaves as if seeded by Seed(1). That is not a joke - actually for a PRNG to be deterministic and repeatable is desirable in many cases.

For different numbers, seed with a different value, such as time.Now().UnixNano().

答案3

得分: 0

除了其他答案之外,关于这个问题在Medium文章中找到了很好的解释go-how-are-random-numbers-generated

> Go实现了两个用于生成随机数的包:
>
> - 在math/rand包中实现了一个伪随机数生成器(PRNG)
> - 在crypto/rand包中实现了一个加密伪随机数生成器(CPRNG)
>
> 如果两者都可以生成随机数,那么你的选择将基于真正随机数和性能之间的权衡。

正如其他答案所解释的那样,math/rand包从一个源中读取随机数。所以如果你需要随机数,你需要调用rand.Seed()来设置随机种子。

在其他情况下,你可以使用crypto/rand包来生成随机数。它生成的随机数是不确定的。但是性能比math/rand包稍低。

我在下面添加了一个示例代码。你可以运行并查看不同的输出这里

package main

import (
	"crypto/rand"
	"math/big"
)

func main() {
	for i := 0; i < 4; i++  {
		n, _ := rand.Int(rand.Reader, big.NewInt(100))
		println(n.Int64())
	}
}
英文:

Addition to the other answers, good explanation found about this in medium article go-how-are-random-numbers-generated

> Go implements two packages to generate random numbers:
>
> - a pseudo-random number generator (PRNG) in the package math/rand cryptographic
> - pseudorandom number generator (CPRNG), implemented in crypto/rand
>
> If both generate random numbers, your choice will be based on a
> tradeoff between genuinely random numbers and performance.

As other answers explain, math/rand packages populate random numbers reading from a source. So if you need random numbers, you need to set random seed calling rand.Seed()

In other case you can use crypto/rand package to generate random numbers. It generates random numbers which can not be deterministic. But performance is bit lower than math/rand package.

I have added sample code below for that. you can run and see different out put here.

package main

import (
	&quot;crypto/rand&quot;
	&quot;math/big&quot;
)

func main() {
	for i := 0; i &lt; 4; i++  {
		n, _ := rand.Int(rand.Reader, big.NewInt(100))
		println(n.Int64())
	}
}

huangapple
  • 本文由 发表于 2021年7月1日 10:50:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/68203678.html
匿名

发表评论

匿名网友

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

确定