这里可以找到生成随机bool
值的示例(不一定是最快的解决方案,因为那并不是要求):
如何在Go中让函数随机返回true或false
此类算法中最慢的部分始终是获取随机数据(随机信息)。例如,rand.Int31()
调用返回31位随机比特,但如果我们仅将其用于“生成”随机bool
值(这是1位信息),我们会浪费30位(这可能是30个额外的随机bool
值!)。
使用
rand.Source
是一个不错的选择,因为我们不需要
rand.Rand
对随机数据进行所有的 "代码功夫"。我们只需要一个随机信息源。
rand.Source
定义了一种获取随机信息的方法:
Int63() int64
这个
Source.Int63()
方法返回 63 位随机数;为了更快,我们应该使用全部。当然,生成一个单独的
bool
值只需要其中的 1 位,但是我们应该存储剩余的部分,并在后续请求随机
bool
时使用它们。
下面是实现方法:
type boolgen struct {
src rand.Source
cache int64
remaining int
}
func (b *boolgen) Bool() bool {
if b.remaining == 0 {
b.cache, b.remaining = b.src.Int63(), 63
}
result := b.cache&0x01 == 1
b.cache >>= 1
b.remaining--
return result
}
创建这样一个
boolgen
的方法如下:
func New() *boolgen {
return &boolgen{src: rand.NewSource(time.Now().UnixNano())}
}
使用示例:
r := New()
for i := 0; i < 100; i++ {
if i%10 == 0 {
fmt.Println()
}
fmt.Print(r.Bool(), " ")
}
示例输出(在Go Playground上尝试):
false false true true false false false false false false
false false false true false false true false true true
false false true false true false false true true true
false false false false false false false true true false
true true true true false false false false true false
true true true false true true true true true true
true true false true true false false true false true
true true false false false true true true true false
true false false true true true true false false true
true false false false false false false false true false
一些注意事项:
rand.NewSource()
返回的 Source
对于多个 goroutine 的并发使用是不安全的,因此我们的 boolgen
也不适合在多个 goroutine 中同时使用。这一方面是好的,因为它比使用 rand
包的默认源(该源在这方面是安全的,顺便说一下,这个源是未导出的,因此只能通过 rand
包的函数间接 "访问")更快(因为不涉及同步)。
如果需要从多个 goroutine 中使用这个函数,最快的方式(跟问题精神相符)就是所有 goroutine 创建自己的 boolgen
,这样就不需要同步。
如果必须使 boolgen
本身支持并发使用,则仅需要保护其 Bool()
方法以使用 sync.Mutex
。