您的位置:首页 > 编程语言 > C语言/C++

C++生成随机数—生成任意范围内的等概率随机数方法

2017-03-28 16:08 309 查看
原文:
http://www.pc6.com/infoview/Article_50245.html http://www.cnblogs.com/afarmer/archive/2011/05/01/2033715.html http://www.verydemo.com/demo_c92_i78997.html
rand()函数返回0到RAND_MAX之间的伪随机数(pseudorandom)。RAND_MAX常量被定义在stdlib.h头文件中。其值等于32767,或者更大。

srand()函数使用自变量n作为种子,用来初始化随机数产生器。只要把相同的种子传入srand(),然后调用rand()时,就会产生相同的随机数序列。因此,我们可以把时间作为srand()函数的种子,就可以避免重复的发生。如果,调用rand()之前没有先调用srand(),就和事先调用srand(1)所产生的结果一样。

产生随机数的用法
1) 给srand()提供一个种子,它是一个unsigned int类型;
2) 调用rand(),它会根据提供给srand()的种子值返回一个随机数(在0到RAND_MAX之间);
3) 根据需要多次调用rand(),从而不间断地得到新的随机数;
4) 无论什么时候,都可以给srand()提供一个新的种子,从而进一步“随机化”rand()的输出结果。

0~RAND_MAX之间的随机数程序

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
srand((unsigned)time(NULL));
for(int i = 0; i < 10;i++ )
cout << rand() << '\t';
cout << endl;
return 0;
}

产生一定范围随机数的通用表示公式
要取得[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)。

BUT

————————————————————————————————————————————————

假如你想用C++来生成0——N-1之间的随机数,你会怎么做?你可能会说,很简单,看:

srand( (unsigned)time( NULL ) );
rand() % N;

仔细想一下,这个结果是随机的吗(当然,我们不考虑rand()函数的伪随机性)?

不是的,因为rand()的上限是RAND_MAX,而一般情况下,RAND_MAX并不是N的整数倍,那么如果RAND_MAX % = r,则0——r之间的数值的概率就要大一些,而r+1——N-1之间的数值的概率就要小一些。还有,如果N > RAND_MAX,那该怎么办?

一种非常简单的方式,那就是使用

random_shuffle( RandomAccessIterator _First, RandomAccessIterator _Last ).

例如,生成0——N-1之间的随机数,可以这么写

#include
#include

long myrandom( long N )
{
std::vector vl( N ); // 定义一个大小为N的vector
for ( long i=0; i
{
vl[i] = i;
}

std::random_shuffle( vl.begin(), vl.end() );

return (*vl.begin());
}

random_shuffle 还有一个三参数的重载版本

random_shuffle( RandomAccessIterator _First, RandomAccessIterator _Last, RandomNumberGenerator& _Rand )

第三个参数可以接受一个自定义的随机数生成器来把前两个参数之间的元素随机化。

这个方法的缺陷就是,如果只是需要一个随机数的话,当N很大时,空间消耗很大!

——————————————————————————————————————

------解决方案--------------------------------------------------------
取10到20间的随机数应该这样写
a[i]= 10+ (rand()% 11);

一般的如果你希望取得 a到b之间(b>a,包含a和b)的随机数,
可这样写:
a[i]= a + (rand()% (b-a+1));
------解决方案--------------------------------------------------------
假如0..9共10个元素随机划分为0..2共3块:
第0块,从0..10-3随机选出比如5,即0..5归第0块
第1块,从5+1..10-2随机选出比如7,即6,7归第1块
第2块,从7+1..10-1,即8,9归第2块。

现在有一个问题是,如果 N 大于RAND_MAX,应该怎么处理?

这里N=135534747, 需要划分为10个片段,应该怎么随机划分?
https://www.zhihu.com/question/24297923
使用C++11 最好的解决方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: