随机数生成整理(C++,Go)

       年前被随机数困扰了一下,年后才有时间来进行整理记录。随机数生成分为真、伪两种。通常用开发语言自带的随机函数来生成即可,

但碰上较真的情况,可以调用第三方的真随机生成库或系统特殊设备来生成真随机数。

Linux下可以用"/dev/random"或"/dev/urandom"来生成。
关于这两个文件可以看下维基百科:
    https://zh.wikipedia.org/wiki//dev/random

整理了C++和Go版本随机相关的代码如下:

#include <iostream>
#include <random>
#include <chrono>
#include <functional>
 
//
// 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<int>(99000000,99000010),std::mt19937_64(seed));

    for(int i = 0; i < 10; i++){
         std::cout << dice_rand() << " "  ;
    }
    std::cout<<std::endl;
}

// 0/1 true/false  随机
void t2(){
    std::default_random_engine generator;
    std::bernoulli_distribution distribution(0.5);

    for(int i = 0; i < 10; i++){
         std::cout << distribution(generator) << " "  ;
    }
    std::cout<<std::endl;
}

 int main(){
    t1();
    t2();
    return 0;
}



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()
}

    编码时发现,C++11在随机数生成引擎和随机数分布上封装了更多的选择,第三方库也比较多,Go的话,如果要实现一些特别要求的随机效果,则需要手工做更多的处理才行。

    另外,随机数生成在实际使用时,不注意的话,新手常犯的一个错误是种子定的不合理,如在Go中,有些人会用"time.Now().Unix()"做为随机种子,然后在for{}中批量

生成随机数,然后发现得到了很多重复的随机数,我已被同事坑过。。。 


Blog: http://blog.csdn.net/xcl168









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值