首页 > 编程知识 正文

随机数函数c语言,c++产生随机数的函数

时间:2023-05-06 02:47:07 阅读:49710 作者:134

我们知道在c语言中,可以提供随机数的rand (有函数,rand )函数的范围从0到32727。 假设rand ()产生的随机数在0到32727的范围内是等概率的。 如果需要获得小范围的随机数,如0到55之间的随机数,可以采用rand () u。 但是,为了得到更大范围的随机数,rand ()不能满足我们的要求。

1、用大随机函数生成小随机函数

等概率Rand5产生等概率Rand3

问题说明:现在有一个名为Rand5的函数,可以生成等概率的[0]。

5 )范围内的随机整数必须使用此函数来生成Rand3函数(除此之外,不能使用产生随机数的函数或数据源)等概率的0。

3 )范围内的随机整数。

int Rand3() )。

{

int x;

德奥

{

x=Rand5 (;

}while(x=3);

返回x;

}

让我证明一下:

以输出0为例,看看概率是多少。 的第一个有效数值在Rand5中获得。 Rand5返回0的概率是1/5。 如果这件事发生了,我们会得到0。 否则,只有在Rand5返回3或4时,我们才有机会再次调用它以获得新数据。 这是重复的,在第二次调用Rand5之后,循环继续进行,同时以1/5的概率得到0,以2/5的概率得到3或4。 因此,概率的计算公式如下。

根据计算,Rand3输出0的概率确实是1/3,对于其他两个数字也是同样的。 根据计算,Rand3输出0的概率确实是1/3,对于其他两个数字也是同样的。

2、用小随机函数生成大随机函数

主题:已知有rand7(的函数,能够生成等概率[ 0,7 ]范围内的随机整数。 利用该rand7)构建rand10 )函数,生成等概率的[ 0,10 ]范围内的随机整数。

分析: rand10 ) )的整数0-9下的均匀分布,可以构造0-9*n均匀分布的随机整数区间(n为任意正整数)。 如果x是0-9*n区间上的随机整数,则x是在0-9区间上均匀分布的整数。 rand7(*7rand7) )可以生成均匀分布到0-48的随机数,请参考以下说明。 可以去除41~48这样的随机数,得到的数0-40仍然均匀分布到0-40。 这是因为每个数量都可以被视为独立的事件。

为什么rand7(*7rand7) )能产生均匀分布在0-48上的随机数呢?

首先rand7)得到离散的整数集合(0、1、2、3、4、5、6 ),每个整数的出现概率为1/7。 那么,rand7(*7得到离散的整数集合a={0、7、14、21、28、35、42}。 其中,每个整数的出现概率也是1/7。 另一方面,rand7) )得到的集合b={0、1、2、3、4、5、6}的各个整数出现的概率也是1/7。 很明显,集合a和b中任意两个元素的组合可以一一对应于0-48之间的一个整数。 也就是说,0-48之间的任意数量可以唯一地决定a和b中两个元素的组合方式。 相反也成立。 由于a和b元素可以视为独立的事件,因此根据独立事件的概率公式p[ab]=p[a]p[b],得到各组合的概率为1/7*1/7=1/49。 因此,rand7(*7rand7) )生成的整数均匀分布在0到48之间,每个数字的概率为1/49。

接下来的问题是使用0-48的随机数生成0-9的随机数。 如上所述。

int Rand10 () ) )。

{

int x;

德奥

{

x=rand7(*7rand7);

}while(x=

40 );

返回x %

10;

}

总之,如果进一步抽象该问题,则求出random_m (随机数生成器的范围为[0,random_n ) ),求出[0,

n )范围的函数,m n n=m *m

int random_n ()

{

int val=0;

int t; //t是n的最大倍数,且满足t

德奥

{

val=m * random_m () random_m );

}while(val=t );

返回val % n;

}

3 )不均匀概率生成等概率

主题:已知随机函数rand ()在p的概率中发生0,而在1-p的概率中发生1。 现在,为了以1/n的等概率发生1~n之间的任意数,要求设计新的随机函数newRand ) )。

解决方案:随机函数rand ) )等概率为0和1的新随机函数rand ) ),并通过调用k(k是由整数n的二进制表示的位数) (下一个rand ) )函数获得长度为k的0和1的序列由该序列形成的整数是1--n之间的数字。

注意:从产生序列得到的整数有可能大于n,如果大于n的话,则重新产生直至得到的整数不大于n。

第一步:由rand()函数产生Rand()函数,Rand()函数等概率产生0和1

第二步:计算整数n的二进制表示所拥有的位数k,k = 1 +log2n(log以2为底n)

第三步:调用k次Rand()产生随机数,产生的k个01序列表示1-n之间的数

int Rand()

{

int i1 = rand();

int i2 = rand();

if(i1==0 && i2==1)

return 1;

else if(i1==1 &&

i2==0)

return 0;

else

return Rand();

return -1;

}

int newRand()

{

int result = 0;

for(int i = 0 ; i < k ;

++i)

{

if(Rand() == 1)

result |=

(1<

}

if(result > n)

return newRand();

return result;

}

4、如何产生如下概率的随机数?0出1次,1出现2次,2出现3次,n-1出现n次?

我们注意到有如下规律:

n - 1 = (n - 1) + 0 = (n - 2) + 1 = (n - 3) + 2 = ... = 2 + (n - 3)

= 1 + (n - 2) = 0 + (n - 1)

同理n-2

可以发现,满足a + b = n - i的(a, b)数对的个数为n - i + 1个。

所以我们得到如下代码:

int Rand(int n) {

while (1) {

int tmp1 = rand() %

n;

int tmp2 = rand() %

n;

if (tmp1 + tmp2 < n)

{

return

tmp1 + tmp2;

}

}

}

5、用rand产生特别大的随机数

要求:

(1)产生一个比较大的随机数。

(2)产生的随机数在随机范围内等概率。

思路:

1>两个rand相乘

假设我们要产生一个10亿内的随机数,想到rand()可以产生0到32727,那么我们可以采用rand()*rand(),刚好能达到10亿的范围。

可是我们不难发现rand()*rand()会有问题,最大的问题是在规定范围内产生的随机数概率不等,比如一个大于32727的素数,就永远产生不了。而对于很多合数,出现的频率会非常高。

2>按位组合

首先我们找到上限数字的位数,然后对每一位产生一个0到9的随机数,并将产生的一系列0到9的数字组合起来。假设我们要产生一个10亿内的随机数,也就是我们需要产生0到999999999之间的随机数,我们首先求得999999999的位数是9位,然后我们产生9个数字,并将他们组合成一个9位数。比如:872345671,023478652。

看上去没有什么问题,我们很好地解决了一个特别的随即范围,即10亿内。假如我们现在要产生一个60000内的随机数,也就是需要产生一个0到59999之间的数。如果我们按照上述办法,如果产生的数字大于59999,同时也是5位数,比如97863,我们该怎么办?

3>求余法

我们最先想到的是,如果产生的数字(98763)对范围(60000)求余,对一个数字求余,所得到的结果肯定是落在该数字的范围内。

不难发现,我们这里同样有概率问题。对于40000到60000之间的数字,出现的概率为1/100000,对于0到40000之间的数字,出现的概率为2/100000,因此概率不等。

4>逐位检验法

我们将上限数字的逐位取出来,我们逐个产生0到该数字的随机数。对于产生0到59999只的随机数,我们先取第一位:5,我们产生一个0到5之间的随机数,第二位:9,我们产生0到9之间的随机数,最终组合出的5位则是0到59999之间。

我们发现,这也只能解决特殊的数字范围。如果我们要产生一个0到51782之间的随数,这个方法就失效了。比如33216这个数字就产生不了,因为33216第二位3比范围(51782)第二位1大,永远产生不了。

5>丢弃法

同样地,我们首先依然采用组合法产生一个规定位数的数据,如果我们发现我们产生的数字在我们的范围之外,那我们选择丢弃该数据,继续产生随机数,一直到我们产生我们在范围内的随机数。不难证明,丢弃一个不正确的数字本身并不影响产生正确数字的概率。

因此,采用组法+丢弃法能满足我们的要求。

这里只讨论了随机数的上线,对于随机数的下限同理

//产生一个0到9的随机数

static __inline int min_rand()

{

return rand();

}

int my_rand(const int range)

{

short bit = 0; //纪录位数

int tempt = range;

int rand_data = 0;

while ( tempt > 0 )

{

bit++;

tempt = tempt/10;

}

while (bit–)

rand_data = 10*rand_data + min_rand();//组合随机数

if (rand_data >= range)

return my_rand(range);//产生随机数不符合范围,继续

return rand_data;

}

转自:http://blog.csdn.net/martin_liang/article/details/42523183

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。