实现随机数

tech2023-02-12  105

func Seed(seed int64) // 该函数设置随机种子,若不调用此函数设置随机种子,则默认的种子值为1,由于随机算法是固定的,如果每次都以1作为随机种子开始产生随机数,则结果都是一样的,因此一般都需要调用此函数来设置随机种子,通常的做法是以当前时间作为随机种子, 以保证每次随机种子都不同,从而产生的随机数也不同 // 该函数协程安全 // 以下函数用来生成相应数据类型的随机数,带n的版本则生成[0,n)的随机数。 // 注意生成的随机数都是非负数 func Float32() float32 func Float64() float64 func Int() int func Int31() int32 // 注意该函数只返回int32表示范围内的非负数,位数为31,因此该函数叫做Int31 func Int31n(n int32) int32 func Int63() int64 func Int63n(n int64) int64 func Intn(n int) int func Uint32() uint32 func Uint64() uint64 // 另外,rand包还提供了一个类,接口和上面的大致相同: type Rand struct { // ... } // 创建一个以seed为种子的源,注意该源不是协程安全的 func NewSource(seed int64) Source // 以src为源创建随机对象 func New(src Source) *Rand // 设置或重置种子,注意该函数不是协程安全的 func (r *Rand) Seed(seed int64) // 下面的函数和全局版本的函数功能一样 func (r *Rand) Float32() float32 func (r *Rand) Float64() float64 func (r *Rand) Int() int func (r *Rand) Int31() int32 func (r *Rand) Int31n(n int32) int32 func (r *Rand) Int63() int64 func (r *Rand) Int63n(n int64) int64 func (r *Rand) Intn(n int) int func (r *Rand) Uint32() uint32 func (r *Rand) Uint64() uint64

生成随机数时,以当前时间作为随机种子是个很好的选择,可以用time包生成当前时间:

// 返回当前时间 func Now() Time // 为了将Time类型转换为int64类型以作为随机种子 // 可以使用如下两个函数: // 返回从1970年1月1日到t的秒数 func (t Time) Unix() int64 // 返回从1970年1月1日到t的纳秒数 func (t Time) UnixNano() int64 // 生成0-8的随机数 func main() { //协程安全 rand.Seed(time.Now().UnixNano()) w := rand.Intn(9) fmt.Println(w) // 如果要产生负数到正数的随机值,只需要将生成的随机数减去相应数值即可 fmt.Println(rand.Intn(100)-50) // 不是协程安全的 r := rand.New(rand.NewSource(time.Now().UnixNano())) fmt.Println(r.Intn(9)) // 如果要产生负数到正数的随机值,只需要将生成的随机数减去相应数值即可 fmt.Println(r.Intn(100) - 50) // [-50, 50)的随机值 } // 使用goroutine和channel实现一个随机数 package main import ( "fmt" "math/rand" "sync" "time" ) type job struct { value int } type result struct { job *job res int } var jobChan = make(chan *job,10) var resChan = make(chan *result,10) var wg sync.WaitGroup // 1.开启一个goroutine 循环生成随机数,发送到 jobChan func jobDo(a chan<- *job) { defer wg.Done() for { rand.Seed(time.Now().UnixNano()) x := rand.Intn(9) new1 := &job{ value: x, } a <- new1 time.Sleep(time.Microsecond*1000) } } // 2. 从通道ch1 读取数据,然后处理后存入 ch2 中 func resDo(ch1 <-chan *job, ch2 chan<- *result) { defer wg.Done() for { job1 := <-ch1 // 从ch1 中读取数据 处理后,存入ch2 NewRes := &result{ job: job1, res: job1.value, } ch2 <- NewRes } } func main() { wg.Add(1) // 1. 开启一个goroutine 循环生成随机数,发送到 jobChan go jobDo(jobChan) // 2. 开启若干个goroutine从jobChan 中取出随机数,将结果发送给resChan /*wg.Add(1) go resDo(jobChan,resChan)*/ wg.Add(5) for i:=0; i<5; i++ { go resDo(jobChan,resChan) } for result := range resChan { fmt.Println(result.job.value,result.res) } wg.Wait() }

用channel实现随机数

// 用channel实现随机数 package main import "fmt" func main() { var a = make(chan int, 1) var res int for i := 0; i < 32; i++ { select { case a <- 0: res += <-a << uint32(i) fmt.Println("0 out", res, i) case a <- 1: res += <-a << uint32(i) fmt.Println("1 out", res, i) } } res %= 8 fmt.Println(res) } // 随机生成5个随机数 package main import ( "fmt" "math/rand" "sync" "time" ) func main() { out := make(chan int) wg := sync.WaitGroup{} wg.Add(2) go func() { defer wg.Done() for i:=0; i<5; i++ { rand.Seed(time.Now().UnixNano()) out <- rand.Intn(5) } close(out) }() go func() { defer wg.Done() for i:= range out { fmt.Println(i) } }() wg.Wait() }
最新回复(0)