layout: post
title: “随机数浅谈”
subtitle: “随机数的正确打开方式”
date: “2017-04-18”
author: “cj”
tags:
random
c++
c++11
随机数
坏例子:不要使用rand()
注:截图来自rand() Considered Harmful,youtube上也有,演讲者为Stephan T. Lavavej。
Stephan 列出了如下缺陷:
- 不应该使用NULL,而应该使用nullptr
- time()调用时钟周期为1Hz,速度慢
- time()返回值为time_t,隐式转换到srand所需的unsigned int导致编译器产生C4244警告
- srand()接收一个32-bit的种子,精度低
- rand()返回值范围过小[0, 32767]
- 对rand()取余导致结果很大概率上不是均匀分布
- rand()采用线性同余算法,质量低
即使假设rand()结果均匀分布,使用取余(%)仍然有问题:
明显可以得知,当取余对象不能被rand()范围整除时,有一部分数值产生的余数概率略低。上图的例子中,整百数到整百数+99共100个数字可以均匀得到[0,99]之间的结果,但[32700,32767]内只能产生[0,67]之间的结果。
Accelerated C++ 7.4.4节对此有更详尽的描述:
当商(quotient)被当做n且为小整数时,许多伪(pseudo)随机数生成器制造出来的余数(remainder)并不很随机。例如rand()的连续执行结果非偶即奇(这并不十分罕见),这种情况下如果n是2,连续执行rand()%n获得的不是0就是1。
另一方面,如果n是大数,且被