Go 有两个随机数包:
crypto/rand
,它提供了一种获取随机字节的方法math/rand
,它有一个很好的洗牌算法
我想使用 math/rand
中的 Perm
算法,但要为其提供高质量的随机数。
因为两个 rand
包是同一个标准库的一部分,所以应该有一种方法将它们组合在一起,以便 crypto/rand
提供一个很好的源math/rand.Perm
用来生成排列的随机数。
这里(以及 Playground )是我为连接这两个包而编写的代码:
package main
import (
cryptoRand "crypto/rand"
"encoding/binary"
"fmt"
mathRand "math/rand"
)
type cryptoSource struct{}
func (s cryptoSource) Int63() int64 {
bytes := make([]byte, 8, 8)
cryptoRand.Read(bytes)
return int64(binary.BigEndian.Uint64(bytes) >> 1)
}
func (s cryptoSource) Seed(seed int64) {
panic("seed")
}
func main() {
rnd := mathRand.New(&cryptoSource{})
perm := rnd.Perm(52)
fmt.Println(perm)
}
此代码有效。理想情况下,我不想自己定义 cryptoSource
类型,而只是将两个 rand
包放在一起,以便它们一起工作。那么在某处是否有此 cryptoSource
类型的预定义版本?
最佳答案
这基本上就是您需要做的。对于 math/rand
的常见用法,您通常不需要加密安全的随机源,因此没有提供适配器。通过直接在值中分配缓冲区空间,而不是在每次调用时都分配一个新 slice ,您可以使实现稍微高效一些。然而,在读取操作系统随机源失败的不太可能发生的情况下,这将需要 panic 以防止返回无效结果。
type cryptoSource [8]byte
func (s *cryptoSource) Int63() int64 {
_, err := cryptoRand.Read(s[:])
if err != nil {
panic(err)
}
return int64(binary.BigEndian.Uint64(s[:]) & (1<<63 - 1))
}
关于random - 使用 crypto/rand 通过 rand.Perm 生成排列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40965044/