首先我们来说说C++中的随机数生成:
我们知道在C++用函数rand()获取的是一个0 ~ RAND_MAX之间的一个随机数。其中RAND_MAX的值为32767。
首先我们来分析两个程序:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
using namespace std;
int main()
{
srand(time(0));
for(int i=0;i<10;i++)
{
int t = rand();
cout<<t<<endl;
}
return 0;
}
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
using namespace std;
int main()
{
for(int i=0;i<10;i++)
{
srand(time(0));
int t = rand();
cout<<t<<endl;
}
return 0;
}
我们分别输出这两个程序的结果会发现,第一个程序结果为:
而第二个程序的结果是:
很明显,我们希望得到第一种结果。那么把srand(time(0))放到循环体内和放到循环体外有什么不同?
现在我来详细解释上面的结果。
我们首先要明确,对于函数srand(int num)和函数rand()它们是定义在头文件<stdlib.h>里的。
而srand(int num)函数的作用是散布num个随机数,当用rand()时,获取的是散布的这num个数中的任意一个。
rand()函数返回随机数序列中的下一个数,实际上srand(int num)函数是一个伪随机数序列,序列中的每一个数是由对其前面的数字进行复杂变换得到的。为了模仿真正的随机性,首先要调用srand()函数给序列设置一个种子。为了更好地满足随机性,使用了时间函数time(),以便取到一个随时间变化的值,使每次运行rand()函数时从srand()函数所得到的种子值不相同。伪随机数生成器将作为 "种子 "的数当作初始整数传给函数。这粒种子会使这个球(生成伪随机数)一直滚下去。
time(0)返回的是一个整数,这个整数的值等于1970年1月1日0时0分0秒至现在的秒数。所以这样随着时间的不同,生成的随机数的个数也不同。
至于第二个程序中所有的数字都相同,那是因为本身循环并不多,每个循环时间间隔很近,所以实际上time(0)的值都一样。这样相当于每次都是取随机序列中的第一个元素,那当然就一样了。
上面提到了生成的随机序列实际上是一个伪随机序列,其实后面的数是根据前面的数经过复杂的变换得到的。我们可以来看看srand(int num)函数的大体实现原理。
#include <iostream>
#include <string.h>
#include <time.h>
#include <stdio.h>
#define RANDOM_MAX 0x7FFFFFFF
using namespace std;
static long do_rand(unsigned long *value)
{
/*
这个算法保证所产生的值不会超过(2^31 - 1)
这里(2^31 - 1)就是 0x7FFFFFFF。而 0x7FFFFFFF
等于127773 * (7^5) + 2836,7^5 = 16807。
整个算法是通过:t = (7^5 * t) mod (2^31 - 1)
这个公式来计算随机值,并且把这次得到的值,作为
下次计算的随机种子值。
*/
long quotient, remainder, t;
quotient = *value / 127773L;
remainder = *value % 127773L;
t = 16807L * remainder - 2836L * quotient;
if (t <= 0)
t += 0x7FFFFFFFL;
return ((*value = t) % ((unsigned long)RANDOM_MAX + 1));
}
static unsigned long next = 1;
int rand(void)
{
return do_rand(&next);
}
void srand(unsigned int seed)
{
next = seed;
}
int main()
{
srand((unsigned)(time(NULL)));
for(int i=0;i<100; i++)
{
if(i % 10 == 0) puts("");
printf("%d\t",rand()%99+1);
}
return 0;
}
经过上面的分析,就很容易获取一个0 ~ 1之间的一个随机小数。因为随机数中RAND_MAX最大,那么就很容易了:
double get_rand()
{
return (double)rand() / (double)RAND_MAX;
}
在很多重要的算法中,我们没有用srand(int num)函数而直接用rand()来获取随机数,比如Miller素数测试,大数分解 等等。这时实际上有一个默认的随机种 子,这个随机序列是固定的。
那么,Java中的随机数又是怎么样的呢?
在java语言中生成随机数的方法有三种:
1.通过System.currentTimeMillis()方法获取当前时间的毫秒数(long);
2.通过Math.random()方法获取一个介于0到1之间的伪随机数;
3.通过Random类获取随机数;
在Random类中,使用了一个48位的种子数,并通过线性同于公式进行随机数的生成(参考《The Art of Computer Programming, Volume 2》书的3.2.1节。
Random rand = new Random(System.currentTimeMillis());
在Java 中我们可以使用java.util.Random类来产生一个随机数发生器。它有两种形式的构造函数,分别是Random()和Random(long seed)。Random()使用当前时间即System.currentTimeMillis()作为发生器的种子,Random(long seed)使用指定的seed作为发生器的种子。
随机数发生器(Random)对象产生以后,
通过调用不同的method:nextInt(),nextLong(),nextFloat(),nextDouble()等获得不同类型随机数。
生成随机数
Random random = new Random();
Random random = new Random(100);//指定种子数100
random调用不同的方法,获得随机数。
import java.util.Random;
public class Srand {
public static void main(String[] args){
Random random = new Random(100);
System.out.println(random.nextInt());
System.out.println(random.nextFloat());
System.out.println(random.nextBoolean());
}
}
注意Java的Math类中也有一个random()方法,即Math.random()返回的是一个范围为[0.0,1.0)之间的小数。
在Java中,下面的代码表示生成10个0到49之间的随机数。
import java.util.Random;
public class Srand {
public static void main(String[] args){
Random random = new Random();
for(int i=0;i<10;i++){
System.out.println(random.nextInt(50));
}
}
}
在Python中,随机数的生成需要先导入random模块。
1.random.random()用于生成一个0到1的随机符小数: 0 <= n < 1.0
>>> import random
>>> random.random()
0.9658869832707923
>>>
2.random.uniform的函数原型为:random.uniform(a, b),用于生成一个指定范围内的随机符点数,两个参数一 个是上限,一个是下限。如果a > b,则生成的随机数n: a <= n <= b。如果 a<b, 则 b <= n <= a。
>>> random.uniform(1,10)
8.241539762435707
>>> random.uniform(10,1)
5.2752945576846075
>>>
3.random.randint()的函数原型为:random.randint(a, b),用于生成一个指定范围内的整数。其中参数a是下限, 参数b是上限,生成的随机数n: a <= n <= b
>>> random.randint(1,10)
8
>>> random.randrange(0,100,2)
20
>>> random.choice('ACdreamers')
'e'
6.random.shuffle的函数原型为:random.shuffle(x[, random]),用于将一个列表中的元素打乱。
>>>
p = ['ACdreamers','Hello','World','NiHao']
>>> random.shuffle(p)
>>> print p
['World', 'Hello', 'ACdreamers', 'NiHao']
>>>
7.random.sample的函数原型为:random.sample(sequence, k),从指定序列中随机获取指定长度的片断。sample函数不会修改原有序列。 如果k大于sequence元素个数的话会报错。
>>> random.sample('ACdreamers',2)
['s', 'a']
>>>