我试图在Go中生成随机数(整数),但无济于事。我在crypto/rand
中找到了rand
包,这似乎是我想要的,但我无法从文档中看出如何使用它。这就是我现在正在尝试的事情:
b := []byte{}
something, err := rand.Read(b)
fmt.Printf("something = %v\n", something)
fmt.Printf("err = %v\n", err)
但不幸的是,这总是输出:
something = 0
err = <nil>
有没有办法解决这个问题,以便它实际生成随机数?或者,有没有办法设置生成的随机数的上限?
答案 0 :(得分:27)
根据您的使用案例,另一个选项是math/rand
包。如果您生成的数字需要完全不可预测,请不要这样做。如果您需要获得可重现的结果,这会很有帮助 - 只需传入您第一次传递的相同种子。
这是经典的“使用当前时间生成发电机并生成数字”程序:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
fmt.Println(rand.Int())
}
答案 1 :(得分:24)
crypto/rand
仅提供随机数据的二进制流,但您可以使用encoding/binary
从中读取整数:
package main
import "encoding/binary"
import "crypto/rand"
func main() {
var n int32
binary.Read(rand.Reader, binary.LittleEndian, &n)
println(n)
}
答案 2 :(得分:16)
截至2012年4月1日,在发布稳定版本的lang之后,您可以执行以下操作:
package main
import "fmt"
import "time"
import "math/rand"
func main() {
rand.Seed(time.Now().UnixNano()) // takes the current time in nanoseconds as the seed
fmt.Println(rand.Intn(100)) // this gives you an int up to but not including 100
}
答案 3 :(得分:0)
您还可以开发自己的随机数生成器,可能基于简单的“沙漠岛 PRNG”,即线性同余生成器。另外,查找 L'Ecuyer (1999)、Mersenne Twister 或 Tausworthe 生成器...
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
(避免使用 RANDU,它在 1960 年代很流行,但生成的随机数落在 3 空间中的 15 个超平面上)。
package pmPRNG
import "errors"
const (
Mersenne31 = 2147483647 // = 2^31-1
Mersenne31Inv = 1.0 / 2147483647.0 // = 4.656612875e-10
// a = 16807
a = 48271
)
// Each stream gets own seed
type PRNGStream struct {
state int
}
func PRNGStreamNew(seed int) *PRNGStream {
prng := (&PRNGStream{})
prng.SetSeed(seed)
return prng
}
// enforce seed in [1, 2^31-1]
func (r*PRNGStream) SetSeed(seed int) error {
var err error
if seed < 1 || seed > Mersenne31 {
err = errors.New("Seed OOB")
}
if seed > Mersenne31 { seed = seed % Mersenne31 }
if seed < 1 { seed = 1 }
r.state = seed
return err
}
// Dig = Park-Miller DesertIslandGenerator
// integer seed in [1, 2^31-1]
func (r*PRNGStream) Dig(seed int) float32 {
xprev := r.state // x[i-1]
xnext := (a * xprev) % Mersenne31 // x[i] = (a*x[i-1])%m
r.state = xnext // x[i-1] = x[i]
Ri := float32(xnext) * Mersenne31Inv // convert Ui to Ri
return Ri
}
func (r*PRNGStream) Rand() float32 {
r.state = (uint64_t)*r.state * Multby % 0x7fffffff
return float32(r.state) * Mersenne31Inv
}
一些相关链接:
https://en.wikipedia.org/wiki/Lehmer_random_number_generator
你可以使用这个函数来更新你的 x[i+1],而不是上面的那个, val = ((状态 * 1103515245) + 12345) & 0x7fffffff (基本上是a、c、m的不同值)
https://www.redhat.com/en/blog/understanding-random-number-generators-and-their-limitations-linux
https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf