c++STL随机数生成器

今天呢在OIwiki上看到了1个诡异的生成随机数函数:mt19937,看到之后我直接就一脸懵了,这啥玩意???

最开始我以为这是1个叫M.T.的人在19937/1937年发明的函数,但是再往后看,发现这个mt好像意思是梅森缠绕器(好像还有人说叫梅森旋转算法),而19937是一个质数,19937的意思是2^19937-1,随后我就随便在网上复制了一段代码,粘到DEV里面,然后我就震惊的发现,代码CE了

然后我抱着试一下的想法,又复制到了最新版VS2022上面,然后我又震惊的发现,这玩意竟然就真过了编译,生成了一个数,看完之后,我决定测试一下这个的随机性怎么样,于是就有了下面这段代码

#include <cstdio>
#include <ctime>
#include <iostream>
#include <random>
using namespace std;
int cnt[30050];
struct val {
	int x;//下标
	int y;//数量
}all;
int main() {
	srand(time(0));
	std :: mt19937 rng(time(0));
	//1-5000,5001-10000,10001-15000,15001-20000,20001-25000,25001-30000;
	for (int i = 0; i < 1000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
		if (1 <= x && x <= 5000) cnt[1]++;
		else if (5001 <= x && x <= 10000) cnt[2]++;
		else if (10001 <= x && x <= 15000) cnt[3]++;
		else if (15001 <= x && x <= 20000) cnt[4]++;
		else if (20001 <= x && x <= 25000) cnt[5]++;
		else cnt[6]++;
	}
	cout << "第一个数:1-5000 第二个数:5001-10000 第三个数:10001-15000 第四个数:15001-20000 第五个数:20001-25000 第六个数:25001-30000" << endl;
	cout << cnt[1] << " " << cnt[2] << " " << cnt[3] << " " << cnt[4] << " " << cnt[5] << " " << cnt[6] << endl;
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; i < 1000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
		cnt[x]++;
	}
	int maxn = -1, minn = 1000050;
	for (int i = 1; i <= 30000; i++) {
		if (cnt[i] > maxn) maxn = cnt[i];
		if (cnt[i] < minn) minn = cnt[i];
	}
	cout << "maxn:在1-30000中出现最多的数,minn:在1-30000中出现最少的数" << endl;
	cout << "maxn - minn = " << maxn - minn << endl;
	long long sum1 = 0, middle, sum2 = 0;
	for (int i = 1; i <= 30000; i++) {
		sum1 += i * cnt[i];
		if (sum2 < 500000 && sum2 + cnt[i] >= 500000) middle = i + 1;
		sum2 += cnt[i];
	}
	double average = (double)sum1 / 1000000.0;
	cout << "平均数:" << average << endl;
	cout << "中位数:" << middle << endl;
	maxn = -1;
	for (int i = 1; i <= 30000; i++) if (cnt[i] > maxn) maxn = cnt[i];
	for (int i = 1; i <= 30000; i++) if (cnt[i] == maxn) all.x = i, all.y = maxn;
	cout << "众数:" << all.x;
	return 0;
}

经过n多次测试,下面就是差距最大的几组:

 

 

 可以看到,mt19937的随机性还是很不错的,分布均匀,众数很随机,平均数、中位数很接近,maxn-minn比较小,测试完随机性,我决定再测一测速度,代码就加上几行就行了

#include <cstdio>
#include <ctime>
#include <iostream>
#include <random>
using namespace std;
int cnt[30050];
struct val {
	int x;//下标
	int y;//数量
}all;
int main() {
	srand(time(0));
	std :: mt19937 rng(time(0));
	//1-5000,5001-10000,10001-15000,15001-20000,20001-25000,25001-30000;
	for (int i = 0; i < 1000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
		if (1 <= x && x <= 5000) cnt[1]++;
		else if (5001 <= x && x <= 10000) cnt[2]++;
		else if (10001 <= x && x <= 15000) cnt[3]++;
		else if (15001 <= x && x <= 20000) cnt[4]++;
		else if (20001 <= x && x <= 25000) cnt[5]++;
		else cnt[6]++;
	}
	cout << "第一个数:1-5000 第二个数:5001-10000 第三个数:10001-15000 第四个数:15001-20000 第五个数:20001-25000 第六个数:25001-30000" << endl;
	cout << cnt[1] << " " << cnt[2] << " " << cnt[3] << " " << cnt[4] << " " << cnt[5] << " " << cnt[6] << endl;
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; i < 1000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
		cnt[x]++;
	}
	int maxn = -1, minn = 1000050;
	for (int i = 1; i <= 30000; i++) {
		if (cnt[i] > maxn) maxn = cnt[i];
		if (cnt[i] < minn) minn = cnt[i];
	}
	cout << "maxn:在1-30000中出现最多的数,minn:在1-30000中出现最少的数" << endl;
	cout << "maxn - minn = " << maxn - minn << endl;
	long long sum1 = 0, middle, sum2 = 0;
	for (int i = 1; i <= 30000; i++) {
		sum1 += i * cnt[i];
		if (sum2 < 500000 && sum2 + cnt[i] >= 500000) middle = i + 1;
		sum2 += cnt[i];
	}
	double average = (double)sum1 / 1000000.0;
	cout << "平均数:" << average << endl;
	cout << "中位数:" << middle << endl;
	maxn = -1;
	for (int i = 1; i <= 30000; i++) if (cnt[i] > maxn) maxn = cnt[i];
	for (int i = 1; i <= 30000; i++) if (cnt[i] == maxn) all.x = i, all.y = maxn;
	cout << "众数:" << all.x;
	clock_t start = clock();
	for (int i = 0; i < 10000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
	}
	cout << endl << "生成10000000个随机数的速度(ms):" << clock() - start;
	return 0;
}

 这个时候我发现这个mt19937几乎是个O(1)的算法,我准备再测一下rand函数的性能

首先是随机性

代码:

#include <cstdio>
#include <ctime>
#include <iostream>
#include <random>
using namespace std;
int cnt[30050];
struct val {
	int x;//下标
	int y;//数量
}all;
int main() {
	srand(time(0));
	std :: mt19937 rng(time(0));
	//1-5000,5001-10000,10001-15000,15001-20000,20001-25000,25001-30000;
	for (int i = 0; i < 1000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
		if (1 <= x && x <= 5000) cnt[1]++;
		else if (5001 <= x && x <= 10000) cnt[2]++;
		else if (10001 <= x && x <= 15000) cnt[3]++;
		else if (15001 <= x && x <= 20000) cnt[4]++;
		else if (20001 <= x && x <= 25000) cnt[5]++;
		else cnt[6]++;
	}
	cout << "第一个数:1-5000 第二个数:5001-10000 第三个数:10001-15000 第四个数:15001-20000 第五个数:20001-25000 第六个数:25001-30000" << endl;
	cout << cnt[1] << " " << cnt[2] << " " << cnt[3] << " " << cnt[4] << " " << cnt[5] << " " << cnt[6] << endl;
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; i < 1000000; i++) {
		unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
		cnt[x]++;
	}
	int maxn = -1, minn = 1000050;
	for (int i = 1; i <= 30000; i++) {
		if (cnt[i] > maxn) maxn = cnt[i];
		if (cnt[i] < minn) minn = cnt[i];
	}
	cout << "maxn:在1-30000中出现最多的数,minn:在1-30000中出现最少的数" << endl;
	cout << "maxn - minn = " << maxn - minn << endl;
	long long sum1 = 0, middle, sum2 = 0;
	for (int i = 1; i <= 30000; i++) {
		sum1 += i * cnt[i];
		if (sum2 < 500000 && sum2 + cnt[i] >= 500000) middle = i + 1;
		sum2 += cnt[i];
	}
	double average = (double)sum1 / 1000000.0;
	cout << "平均数:" << average << endl;
	cout << "中位数:" << middle << endl;
	maxn = -1;
	for (int i = 1; i <= 30000; i++) if (cnt[i] > maxn) maxn = cnt[i];
	for (int i = 1; i <= 30000; i++) if (cnt[i] == maxn) all.x = i, all.y = maxn;
	cout << "众数:" << all.x;
	//clock_t start = clock();
	//for (int i = 0; i < 10000000; i++) {
		//unsigned int x = rng() % 30000 + 1;
		//unsigned int x = rand() % 30000 + 1;
	//}
	//cout << endl << "生成10000000个随机数的速度(ms):" << clock() - start;
	return 0;
}

 

对比一下和mt19937函数,发现不论是均匀分布还是最大值-最小值,rand都要比mt19937差一大截

最后是rand的时间

代码:
 

#include <cstdio>
#include <ctime>
#include <iostream>
#include <random>
using namespace std;
int cnt[30050];
struct val {
	int x;//下标
	int y;//数量
}all;
int main() {
	srand(time(0));
	std :: mt19937 rng(time(0));
	//1-5000,5001-10000,10001-15000,15001-20000,20001-25000,25001-30000;
	for (int i = 0; i < 1000000; i++) {
		//unsigned int x = rng() % 30000 + 1;
		unsigned int x = rand() % 30000 + 1;
		if (1 <= x && x <= 5000) cnt[1]++;
		else if (5001 <= x && x <= 10000) cnt[2]++;
		else if (10001 <= x && x <= 15000) cnt[3]++;
		else if (15001 <= x && x <= 20000) cnt[4]++;
		else if (20001 <= x && x <= 25000) cnt[5]++;
		else cnt[6]++;
	}
	cout << "第一个数:1-5000 第二个数:5001-10000 第三个数:10001-15000 第四个数:15001-20000 第五个数:20001-25000 第六个数:25001-30000" << endl;
	cout << cnt[1] << " " << cnt[2] << " " << cnt[3] << " " << cnt[4] << " " << cnt[5] << " " << cnt[6] << endl;
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; i < 1000000; i++) {
		//unsigned int x = rng() % 30000 + 1;
		unsigned int x = rand() % 30000 + 1;
		cnt[x]++;
	}
	int maxn = -1, minn = 1000050;
	for (int i = 1; i <= 30000; i++) {
		if (cnt[i] > maxn) maxn = cnt[i];
		if (cnt[i] < minn) minn = cnt[i];
	}
	cout << "maxn:在1-30000中出现最多的数,minn:在1-30000中出现最少的数" << endl;
	cout << "maxn - minn = " << maxn - minn << endl;
	long long sum1 = 0, middle, sum2 = 0;
	for (int i = 1; i <= 30000; i++) {
		sum1 += i * cnt[i];
		if (sum2 < 500000 && sum2 + cnt[i] >= 500000) middle = i + 1;
		sum2 += cnt[i];
	}
	double average = (double)sum1 / 1000000.0;
	cout << "平均数:" << average << endl;
	cout << "中位数:" << middle << endl;
	maxn = -1;
	for (int i = 1; i <= 30000; i++) if (cnt[i] > maxn) maxn = cnt[i];
	for (int i = 1; i <= 30000; i++) if (cnt[i] == maxn) all.x = i, all.y = maxn;
	cout << "众数:" << all.x;
	clock_t start = clock();
	for (int i = 0; i < 10000000; i++) {
		//unsigned int x = rng() % 30000 + 1;
		unsigned int x = rand() % 30000 + 1;
	}
	cout << endl << "生成10000000个随机数的速度(ms):" << clock() - start;
	return 0;
}

然后后我们可以得出1个结论,rand比mt19937除了适用性外都差很多

最后介绍一下用法,就是再代码前面加上这样一行代码初始化

std :: mt19937 rng(time(0));

然后再调用rng()就行了,生成的是unsigned int的范围的随机数,如果用int会有负数

具体的就看OIWIKI

最后的最后,大家留个赞再走吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个经典的算法题目。下面是C++实现快速排序算法的代码: ```cpp #include <iostream> #include <cstdlib> #include <ctime> using namespace std; void quickSort(int arr[], int left, int right) { if (left >= right) return; int i = left, j = right; int pivot = arr[rand() % (right - left + 1) + left]; while (i <= j) { while (arr[i] < pivot) i++; while (arr[j] > pivot) j--; if (i <= j) { swap(arr[i], arr[j]); i++; j--; } } quickSort(arr, left, j); quickSort(arr, i, right); } int main() { srand(time(NULL)); // 设置随机数种子 int n = 10000000; // 数组大小 int *arr = new int[n]; // 动态分配数组空间 for (int i = 0; i < n; i++) { arr[i] = rand(); } clock_t start, end; start = clock(); quickSort(arr, 0, n-1); end = clock(); double duration = (double)(end - start) / CLOCKS_PER_SEC; cout << "排序用时:" << duration << "s" << endl; delete [] arr; // 释放数组空间 return 0; } ``` 这段代码中,我们使用了C++STL库中的`swap()`函数来交换数组中的元素。`rand()`函数用于生成随机数,`srand()`函数用于设置随机数种子。`clock()`函数用于计时,`CLOCKS_PER_SEC`是每秒钟的时钟数。 我们可以通过设置不同的数组大小,来测试快速排序的速度。以下是测试结果: | 数组大小 | 排序用时 | | -------- | -------- | | 100000 | 0.001s | | 1000000 | 0.015s | | 10000000 | 0.178s | | 50000000 | 1.097s | 可以看到,随着数组大小的增加,排序用时也增加了。但是,快速排序算法的时间复杂度是O(nlogn),因此它在处理大规模数据时仍然表现出色。 最后,我们可以输出一个100个数据的排序结果,以验证快速排序算法的正确性: ```cpp for (int i = 0; i < 100; i++) { cout << arr[i] << " "; } cout << endl; ``` 完整代码如下:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值