我想要一个函数,每次调用可以随机返回true
或false
值:
randBoolean() // true
randBoolean() // false
randBoolean() // false
randBoolean() // true
如何返回一个随机的布尔值?
true
和另一半的false
。使用rand.Float32()
来演示非常简单,它是math/rand
包中的函数。func rand1() bool {
return rand.Float32() < 0.5
}
rand.Seed()
来种子化math/rand
包,以使其在每次应用程序运行时都不同:func main() {
rand.Seed(time.Now().UnixNano())
fmt.Println(rand1())
}
math/rand
的包文档中提到:func rand2() bool {
return rand.Int31()&0x01 == 0
}
func rand3() bool {
return rand.Intn(2) == 0
}
这是一种不使用 math/rand
包的有趣解决方案。它使用了 select
语句:
func rand9() bool {
c := make(chan struct{})
close(c)
select {
case <-c:
return true
case <-c:
return false
}
}
解释:
select
语句从可以不阻塞的案例中选择一个随机案例。由于从关闭的通道接收可以立即进行,因此将随机选择2个案例之一,返回true
或false
。请注意,这远非完全随机,因为这并不是select
语句的要求。
通道也可以移动到全局变量中,因此每次调用时无需创建通道和关闭通道:
var c = make(chan struct{})
func init() {
close(c)
}
func rand9() bool {
select {
case <-c:
return true
case <-c:
return false
}
}
rand.Seed()
时,它们总是使用相同的值(1)进行种子化。这实际上可能是一种期望的行为(例如用于测试)。 - Makkes如果随机整数是偶数,则此函数返回true,否则返回false:
func randBool() bool{
return rand.Int() % 2 == 0
}
这是另一个单行代码,不需要任何随机数生成/种子等,非常简单:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Got random bool:", getRandBool())
}
func getRandBool() bool {
now := time.Now()
nowNano := now.Nanosecond()
fmt.Println(nowNano)
return now.UnixNano()%2 == 0
}
在@icza的评论后进行了编辑:time.Now()应该返回纳秒精度的时间,但在Windows 10 Pro 64位上(我尝试过go 1.8,并且可能适用于其他Windows操作系统),它总是以较低的精度(可能是微秒)返回时间,四舍五入结果,以便它以xxxxx..00结尾,因此此函数将始终返回true。我已修改了函数,以便可以看到结果。在Linux上运行良好,可能在其他Unix操作系统上也是如此。因此,如果需要部署在Windows系统上,请在测试后仅使用此功能或最好不要使用。这很不幸,很难相信,但这是现实,是糟糕的Windows实现。感谢@icza指出。
Time.UnixNano()
生成随机getRandBool()
的“随机性”非常依赖于系统时钟的粒度。在某些Windows上,这可能始终返回true
,这是一个“常数”,并不是完全随机的... - icza
rand.Seed
种子化您的 RNG,以便获得非确定性结果。一个相当不错的种子是当前时间(time.Now().UnixNano()
)。 - MakkesSeed
如何工作以及在不调用它时会发生什么的说明。 - Makkes