C++如何实现生成随机数
这篇文章主要讲解了C++如何实现生成随机数,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
成都创新互联公司主营鸡西梨树网站建设的网络公司,主营网站建设方案,重庆APP开发,鸡西梨树h5小程序开发搭建,鸡西梨树网站营销推广欢迎鸡西梨树等地区企业咨询
C风格
C为随机数提供的工具是rand、srand和RAND_MAX,定义在
srand为rand设置种子,如果不设置,相当于调用过srand(1)。rand产生伪随机数,其范围为0到RAND_MAX,RAND_MAX至少是32767,在MSVC和GCC中这个值都是32767。
伪随机数看似随机,实则是有规律可循的,对于相同的种子值,rand产生的序列完全相同,也就是说无论你给srand一个什么数字,多次运行程序的结果都将相同——除非你给srand的是不同的数字,比如时间。
如果我们只需要0到9的随机数,可以把rand的返回值% 10;如果是42到233,可以写rand() % 192 + 42。下面的random函数封装了这项工作。注意只有在b - a + 1远小于或整除RAND_MAX时随机数的分布才比较均匀。
#include#include #include int random(int a, int b) { return rand() % (b - a + 1) + a; } int main() { srand(time(NULL)); printf("RAND_MAX = %d\n", RAND_MAX); for (int i = 0; i < 10; i++) printf("%d ", rand()); printf("\n"); int count[10] = {0}; for (int i = 0; i < 10000; i++) count[random(0, 9)]++; for (int i = 0; i < 10; i++) { printf("%d: ", i); for (int j = 0; j < count[i] / 10; j++) printf("*"); printf("\n"); } }
C++风格
从C++11开始,C++标准规定了随机数设施,包括均匀随机位生成器(Uniform random bit generators,URBG)和随机数分布等,定义在
URBG分为随机数引擎、引擎适配器、预置随机数生成器和非确定随机数生成器4类,通常后两类就够用了。
标准规定了3种随机数引擎:
- 线性同余linear_congruential_engine(LCG),时间空间消耗都少;
- 梅森旋转mersenne_twister_engine(MT),占用较多内存(在PC上可以忽略),计算量较大;
- 带进位减法(属于滞后斐波那契生成器,LFG)subtract_with_carry_engine,性能与效果折中。
随机数引擎都需要一个种子,生成的都是伪随机数。
引擎适配器可以套一个随机数引擎:
- discard_block_engine在连续若干个伪随机数中选择若干个;
- independent_bits_engine把位数多的伪随机数压缩成位数少的;
- shuffle_order_engine把连续若干个伪随机数重排。
套娃的方式是模板,理论上你还可以用适配器套适配器,不过CPU可能会有意见。
随机数引擎的模板参数怎么取?标准定义了一些数学家们发现的效果良好的随机数引擎:LCG minstd_rand0、minstd_rand、knuth_b;MT mt19937、mt19937_64;LFG ranlux24_base、ranlux48_base、ranlux24、ranlux48。如果你还是无从下手,那就用default_random_engine,编译器的开发者们为你选好了他们认为最合适的,在MSVC中是mt19937,在GCC中是minstd_rand0。
以上工具都生成伪随机数,标准还定义了真·随机数引擎random_device,尽管标准也允许它是伪随机的。如果它是真随机的,那么使用起来它的效果无疑是最好的,但是多次调用后性能会急剧下降,通常只用于生成伪随机数引擎的种子。
随机数生成器类型都定义了静态方法min和max,返回生成的随机数的范围,以及无参数的函数调用运算符operator(),返回随机数。
#include#include int main() { auto engine = std::default_random_engine(std::random_device()()); std::cout << "min = " << engine.min() << "; max = " << engine.max() << std::endl; std::cout << "random numbers: "; for (int i = 0; i != 10; ++i) std::cout << engine() << ' '; std::cout << std::endl; }
大多数情况下我们不需要min到max范围的整数,而需要一定分布的整数或实数。标准规定了许多随机数分布类型,我数学不好,不太懂这些。
- 均匀分布uniform_int_distribution、uniform_real_distribution;
- 伯努利分布bernoulli_distribution、binomial_distribution、negative_binomial_distribution、geometric_distribution;
- 泊松分布poisson_distribution、exponential_distribution、gamma_distribution、weibull_distribution、extreme_value_distribution;
- 正态分布normal_distribution、lognormal_distribution、chi_squared_distribution、cauchy_distribution、fisher_f_distribution、student_t_distribution;
抽样分布discrete_distribution、piecewise_constant_distribution、piecewise_linear_distribution。
构造分布实例时传入分布的参数。调用operator()获得结果,参数为随机数引擎。
#include#include #include int main() { auto engine = std::default_random_engine(std::random_device()()); std::uniform_int_distribution uniform(0, 9); int count[10] = {0}; for (int i = 0; i != 10000; ++i) ++count[uniform(engine)]; for (int i = 0; i != 10; ++i) std::cout << i << ": " << std::string(count[i] / 10, '*') << std::endl; }
注意,与STL中左闭右开的习惯不同,uniform_int_distribution构造函数接受的参数是闭区间。
看完上述内容,是不是对C++如何实现生成随机数有进一步的了解,如果还想学习更多内容,欢迎关注创新互联行业资讯频道。
网站题目:C++如何实现生成随机数
文章分享:http://scyanting.com/article/popsps.html