比如,有这样一个需求,现在有一个rand5()函数,这个函数可以生成1-5的随机数,让你通过这个函数生成1-7范围的随机数。
怎么做了?
一般思路是这样的:用两次rang5函数,通过这两次rand5结果,构造出一个随机数范围包括0-7,但比0-7大的范围就好了。比如(rand5 -1)*5 +rand5,它的范围为1-25(包括0-7),因为rand5产生每个数随机概率相等,那么(rand5 -1)*5 +rand5产生的每个数的概率也是相等的。我们只要1-7的数,因此代码可以这样写:
int rand5() { int n =1 + rand()%5; return n; } int rand7(){ int n=0; while((n=((rand5 -1)*5 +rand5))>7); return n;}对于上述代码,可能要循环好多次才能得到小于7的数,那么是否可以减少生成次数。可以用模来减少生成次数,因为只要是7的倍数范围,模后每个数的概率是相等的,那么上述代码可以改为:
int rand7(){ int n=0; while((n=((rand5 -1)*5 +rand5))>21); return n%7;}上面的算法有一个问题,我们发现每次洗牌之后原来洗好的牌都会进行二次操作,所以不妨加以改进: a)同样,首先我们生成一个大小为54的数组,数组排列为1~54 b)索引牌从1开始,到54结束。这一次索引牌只和剩下还没有洗的牌进行交换, index= i+ rand() %(size - i) c)等到所有的索引牌都洗好之后,一副牌就弄好了
void Shuffle(vector<int> card) { for(int i=0;i<card.size();i++) { swap(num[i], num[ i+ rand() %(card.size()- i)]); } }参考: 一步一步写算法(之洗牌算法) 给定一个随机函数,求另外一个随机函数
新闻热点
疑难解答