年前被随机数困扰了一下,年后才有时间来进行整理记录。随机数生成分为真、伪两种。通常用开发语言自带的随机函数来生成即可,
但碰上较真的情况,可以调用第三方的真随机生成库或系统特殊设备来生成真随机数。
Linux下可以用"/dev/random"或"/dev/urandom"来生成。整理了C++和Go版本随机相关的代码如下:
#include
#include
#include
#include
//////////////////////////////////////////////////
// C++11 随机数生成例子
//
//参考: http://www.cplusplus.com/reference/random/
// https://www.zhihu.com/question/20423025
// Author: XCL
// Date: 2017-2-12
//////////////////////////////////////////////////
// int 随机
void t1(){
//随机数引擎用uniform_int_distribution,数据分布用mersenne_twister , 范围[99000000, 99000010]
std::mt19937_64::result_type seed = std::chrono::system_clock::now().time_since_epoch().count();
auto dice_rand = std::bind(std::uniform_int_distribution(99000000,99000010),std::mt19937_64(seed));
for(int i = 0; i < 10; i++){
std::cout << dice_rand() << " " ;
}
std::cout<
Go版:
package main
/*
Go的几种随机数生成方式实现整理
参考:
https://zh.wikipedia.org/wiki//dev/random
https://gobyexample.com/random-numbers
https://golang.org/pkg/crypto/rand/
Author: XCL
Date: 2017-2-12
*/
import (
crand "crypto/rand"
"encoding/binary"
"fmt"
mrand "math/rand"
"os"
"time"
)
// int 随机
func a1() {
s1 := mrand.NewSource(time.Now().UnixNano())
r1 := mrand.New(s1)
for i := 0; i < 10; i++ {
fmt.Printf("%d ", r1.Intn(100))
}
fmt.Printf("\n")
}
// 0/1 true/false 随机
func a2() {
// Go编程这本书上例子.
ch := make(chan int, 1)
for i := 0; i < 10; i++ {
select {
case ch <- 0:
case ch <- 1:
}
r := <-ch
fmt.Printf("%d ", r)
}
fmt.Printf("\n")
}
//真随机 -- 用标准库封装好的
func a3() {
b := make([]byte, 16)
// On Unix-like systems, Reader reads from /dev/urandom.
// On Windows systems, Reader uses the CryptGenRandom API.
_, err := crand.Read(b) //返回长度为0 - 32 的值
if err != nil {
fmt.Println("[a3] ", err)
return
}
fmt.Println("[a3] b:", b)
}
//真随机 -- 我们直接调真随机文件生成了事。 但注意,它是阻塞式的。
func a4() {
f, err := os.Open("/dev/random")
if err != nil {
fmt.Println("[a4] ", err)
return
}
defer f.Close()
b1 := make([]byte, 16)
_, err = f.Read(b1)
if err != nil {
fmt.Println("[a4] ", err)
return
}
fmt.Println("[a4] Read /dev/random:", b1)
}
// a3 的另一种实现方式
func a5() {
var ret int32
binary.Read(crand.Reader, binary.LittleEndian, &ret)
fmt.Println("[a5] ret:", ret)
}
func main() {
a1()
a2()
a3()
a4()
a5()
}
另外,随机数生成在实际使用时,不注意的话,新手常犯的一个错误是种子定的不合理,如在Go中,有些人会用"time.Now().Unix()"做为随机种子,然后在for{}中批量
生成随机数,然后发现得到了很多重复的随机数,我已被同事坑过。。。
Blog: http://blog.csdn.net/xcl168