一、
假如要生成一个包含包含9个元素的一维数组,元素分别是1到9这9个整数随机排列,每个数字都出现一次。
产生思路为:
1.产生一个全0的数组A
2.产生一个1到9之间的随机数a
3.将a放到A中
4.继续产生随机数,并判断a是否存在于A中
5.若在则跳过,不在则放入A中
6.9个数字都填完以后结束
运行程序如下`
#include <iostream>
int main()
{
int num[9] = { 0 };
int i = 0;
while (num[8] == 0)
{
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
int a = (rand() % 9) + 1;
int start = 0;
int end = 8;
int* result = find(num + start, num + end, a);
if (result == num + end)
{
num[i] = a;
i++;
}
}
for (int i = 0; i < 9; i++)
cout << num[i] << ' ';
return 0;
}
运行结果如图所示:
结果显示正确
二、
上面写的程序在实际运行时,产生一个数组要花费十秒左右的时间,如果想要快速产生大量数组,比如成百上千个,这段程序就不适用了。
主要原因就出在下面这两行
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
int a = (rand() % 9) + 1;
C++产生随机数是通过rand函数计算得到的,是一种伪随机数,开始计算时需要一个随机种子,当随机种子相同时,得到的随机数也是一样的。所以想得到不同的随机数就要设置不同的随机种子。
srand函数就是设置随机种子的,time(0)的返回值是从1970年1月1日至今所经历的时间(以秒为单位),转换整形后由srand((int)time(0))作为了随机种子,可以保证随机种子的不同。
常见产生随机数的方式,都是用当前时间作为随机种子的,这样做比较简单。但问题就在于产生不同随机种子的时间至少要间隔一秒,当需要产生大量随机数时就会导致时间的增加。所以此时并不适用直接将时间作为随机种子。
改进程序如下:
int main()
{
for (int i = 0; i < 9; i++) //假设要生成9个数组
{
int k = (int)time(0); //只去一次当前时间
int num[9] = { 0 };
int m = 0;
int j = 50 * (i * i * i + 100 + i * i * 5 - 20)+k;
\\这个有关i的表达式是我随便写的,每个人都可以写自己的,只要让当i不同时计算结果差距较大就可以
\\由于每次得到的i不同,与k结合以后的j就都不会相同
while (num[8] == 0)
{
srand(j); //此时就能保证每次的随机种子不同
int a = (rand() % 9) + 1;
int start = 0;
int end = 8;
int* result = find(num + start, num + end, a);
if (result == num + end)
{
num[m] = a;
m++;
}
j++;
}
for (int i1 = 0; i1 < 9; i1++)
{
cout << num[i1];
}
cout << endl;
}
return 0;
}
运行结果如图:
运行结果正确,并且运行时间不到一秒钟。
三、
这段程序同样还有缺点,我在实测产生一百个数组时,发现产生速度虽然韩快,但偶尔会出现两个相邻数组一模一样的情况。我认为还是随机种子的设置不够好,没办法做到完全随机。如果是生成9个数组,没有发现过出现一样的数组。
四、
使用rand产生随机数的公式如下:
要取得[0,n) 就是rand()%n 表示 从0到n-1的数
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。