随机整数数组
math/rand的随机数可以说是一次性的,无论for循环执行几次,无论编译执行几次,结果都一模一样,除非重复写多次代码行,可以说实用性很差。
而crypto/rand的随机数,掌握用法之后,就能得到“真正的随机数”。
如果在迭代算法中需要用到(粒子群,模拟退火,遗传,梯度下降等等)随机数,千万要用crypto,不能用math.rand,否则仅仅是初始化群体,就全部是一模一样的个体,每次迭代也是一样的随机数,那完全不会有一丁点效果。
import (
"crypto/rand"
"fmt"
"math/big"
) //// 虚假的随机数 //func randInt(dim, n int) []int { // var vector []int // rand.Seed(time.Now().UnixNano()) // for i := 0; i < dim; i++ { // vector = append(vector, rand.Intn(n)) // } // return vector //} // 真正的随机数 func randInt(dim, n int) []int { var vector []int for i := 0; i < dim; i++ { res, err := rand.Int(rand.Reader, big.NewInt(5)) if err != nil { fmt.Println(err) } vector = append(vector, int(res.Int64())) } return vector }
实例:
func main() { for i := 0; i < 4; i++ { fmt.Println(randInt(10, 5)) // fmt.Println(uniform(10)) } }
编译执行第一次:
[1 4 3 1 1 3 2 1 0 4]
[4 0 0 2 0 2 0 0 0 1]
[0 3 4 2 0 0 1 0 1 2]
[4 0 1 4 1 4 2 2 4 4]
编译执行第二次:
[3 1 3 1 3 0 2 4 2 1]
[4 0 3 2 1 1 0 1 1 4]
[4 0 3 2 2 1 2 1 0 2]
[2 3 4 2 1 0 1 3 1 0]
---end---
事实上掌握了随机整数数组,实现一个0-1随即小数数组并不难,举例如下,精度为0.01的
// 生成0-1之间随机数的向量 //虚假的随机数 func uniforms(dim int) []float64 { var vector []float64 rand.Seed(time.Now().UnixNano()) for i := 0; i < dim; i++ { vector = append(vector, rand.Float64()) } return vector } // 真正的随机数 func uniform(dim int) []float64 { var vector []float64 for i := 0; i < dim; i++ { res, err := rand.Int(rand.Reader, big.NewInt(100)) if err != nil { fmt.Println(err) } vector = append(vector, float64(res.Int64())/100) } return vector } func main() { for i := 0; i < 4; i++ { // fmt.Println(randInt(10, 5)) fmt.Println(uniform(10)) } }
结果:
[0.33 0.27 0.68 0.97 0.41 0 0.24 0.27 0.45 0.07]
[0.05 0.96 0.76 0.15 0.93 0.01 0.14 0.67 0.99 0.31]
[0.9 0.83 0.84 0.4 0.84 0 0.07 0.96 0.07 0.38]
[0.65 0.6 0.53 0.68 0.2 0.62 0.73 0.13 0.12 0.18]