英文:
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语言的方式:
英文:
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
答案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 (
"crypto/rand"
"math/big"
)
func main() {
for i := 0; i < 4; i++ {
n, _ := rand.Int(rand.Reader, big.NewInt(100))
println(n.Int64())
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论