c++生成真随机数(random与chrono)

扯谈一会

最近在写二叉搜索树,我懂得不多,就再写FHQ treap树。写完后,我做测试时发现树形态变化不大,效果不理想。就想着研究随机树生产器。上网查了一下,东西还是蛮多的,就在此整理一下。

优质的随机数生成器:random

其实c++11已经提供了很好的随机数生成器,包含在 r a n d o m random random头文件,同时需要引用 s t d std std命名空间。随机数生成器一般会用到一下几种:

mt19937 Rand(seed);

使用梅森旋转算法,效率极高,需要一个种子,生成伪随机数。

mt19937_64 Rand(seed);

同上,只是返回 l o n g   l o n g long\ long long long

random_device Rand;

读取系统熵值或特殊文件,是真随机数,但有局限性,在移植时可能有 B u g Bug Bug,有的电脑上多次打开程序会生成一样的数,所以后文不再提到

uniform_int_distribution<T> Rand(L,R);
uniform_real_distribution<T> Rand(L,R);

分别返回L~R的T类型的随机数,原理未知,区别为分别返回整数和浮点数,不推荐使用

高速的时间:chrono

根据上文内容,我们基本可以确定我们将用 m t 19937 mt19937 mt19937作为随机数生成器,因为它虽然生成的是伪随机数,但却有极高的随机性,只需要一个高速变化的种子,这样问题就变成了如何获得随机种子。我们当然可以仍用 t i m e ( 0 ) time(0) time(0)获得种子,但这样不满足高速变化,就会导致短时间内多次打开程序生成的随机数相同。我们也可以用 r a n d o m _ d e v i c e random\_device random_device生成种子,但前面说了,它某些方面有问题,这里也不用它。那怎么办呢?c++11还包含了一个新库: c h r o n o chrono chrono,包含在 c h r o n o chrono chrono头文件,用于获取高精度时间实测可以获取到 1 / 1000000000 1/1000000000 1/1000000000秒左右,精度已经很高了。

chrono库为我们提供了三种时钟类型:system_clocksteady_clockhigh_resolution_clock。这三个时间类都提供了rep(周期)、period(单位比率)、duration(成员类型)。这三个时钟类都提供了一个静态成员函数 now() 用于获取当前时间,该函数的返回值是一个 time_point 类型。

三个时钟的区别:

1.system_clock:类似Windows系统右下角那个时钟,是系统时间。明显这个时钟是可以自己设置的。system_clock除了now()函数外,还提供了to_time_t()静态成员函数。用于将系统时间转换成熟悉的std::time_t类型,得到了std::time_t类型的值,就可以很方便地打印当前时间了。

2.steady_clock:是单调的时钟,相当于教练手中的秒表。只会增长,适合用于记录程序耗时,他表示时钟是不能设置的。

3.high_resolution_clock:是当前系统能够提供的最高精度的时钟。它也是不可以修改的。相当于 steady_clock 的高精度版本。

为了获得更高精度的时间,我会一直使用high_resolution_clock类来获取时间。

现在有了获取时间的工具,但是距离做随机种子还差一步。现在 s t d : : c h r o n o : : h i g h _ r e s o l u t i o n _ c l o c k : : n o w ( ) std::chrono::high\_resolution\_clock::now() std::chrono::high_resolution_clock::now()获取的时间是time_point类型,而且time_point无法直接转成 l o n g   l o n g long\ long long long,也就无法作为随机种子,但它可以用 ( t i m e _ p o i n t 对象 ) . t i m e _ s i n c e _ e p o c h ( ) . c o u n t ( ) (time\_point对象).time\_since\_epoch().count() (time_point对象).time_since_epoch().count()将其转为 u n s i g n e d   l o n g   l o n g unsigned\ long\ long unsigned long long,就可以作为种子了,获取时间的函数如下:

long long get_high_time(){
	return (std::chrono::high_resolution_clock::now()).time_since_epoch().count();
}

封装成果

至此,理论已经讲完了,完整类代码如下:

#ifndef MYRANDOMS
#define MYRANDOMS
#include<bits/stdc++.h>
#include<chrono>
#include<random>
namespace MTL{
	using namespace std;
	class random{
		public:
		int rand_int(int left,int right){
			static mt19937 engine(get_rand_seed());
			int a=right-left+1,sum;
			sum=engine()%a+left;
			return sum;
		}
		long long operator()(long long left,long long right){
			static mt19937_64 engine(get_rand_seed());
			long long a=right-left+1,sum;
			sum=engine()%a+left;
			return sum;
		}
		long long get_high_time(){
			return (std::chrono::high_resolution_clock::now()).time_since_epoch().count();
		}	
		long long get_rand_seed(){
			mt19937_64 Rand(get_high_time());
			return Rand();
		} 
		random(){
			
		}
		string rand_string(int len,string char_set){
			int k=char_set.size()-1;
			string re;
			for(int i=0;i<len;i++){
				re+=(char_set[rand_int(0,k)]);
			}
			return re;
		}
	};
}
#endif

代码不长,相信大家看的懂。

(完结)

  • 28
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值