| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2094 人关注过本帖
标题:随机函数之等概率问题
取消只看楼主 加入收藏
帅的让人抽
Rank: 4
来 自:安徽
等 级:业余侠客
帖 子:94
专家分:224
注 册:2010-9-30
结帖率:100%
收藏
已结贴  问题点数:10 回复次数:3 
随机函数之等概率问题
编写一个函数,通过返回一个范围1至6的随机整数来模拟掷骰子,这6个值出现的概率应该相等。
这个问题大多人做的时候,可能这样做:
程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int fun_throw(void)
{

 //local declarations
 static int is_seeded=0;

 int value;


 //statements


 if(!is_seeded)

 {
  is_seeded=1;
  srand(time(NULL));

 }  //if

value=rand();
return   value%6+1;
}  //fun_throw

int main()
{
  //local declarations 
    int num;
    int i;

 
  //statements    
 printf("请输入要投掷的次数:");

 scanf("%d",&num);

 printf("\n");

 for(i=0;i<num;i++)
     printf("%6d\n",fun_throw());

 return  0;
}  //main

其实这是错的。


随机数函数返回的最大值为32 767(这里就以它为例,标准C规定它至少为32 767),也就是说返回的数在0~32 767之间,总的个数为sum=32768.
为了得到1~6之间的随机整数,我们可以将一个随机数对6取模,得到0~5之间的整数,再将这个值加1便可以了。
在0~32 765之间对6取模得到各个值(0~5)的概率是相等的,每个数字有32 766/6=5461种情况,各个数字发生都是等概率的。但是32 766、32 767对6取模后得到的是0和1 ,加1后得到是1和2.
value=rand()%6+1;
由上面可知,在整个过程中,1和2出现的次数比其他四个数字(3,4,5,6)多了一次,即概率大。
数字1,2在整个过程中出现的概率为5462/32 768,而3,4,5,6出现的概率为5461/32 768.
虽然这个差别很小,但却是不容忽视的。因为这里产生的随机数范围很小而已,我们再看下面的:
如果需要函数产生1~30 000之间的随机数,同样我们可以通过:
value=rand()%30 000+1;
来做。
通过上面的分析我们可知,函数产生的随机数在0~29 999之间通过取模加1得到的是在1~30 000之间的数,它们都均出现一次,概率相等。
但是在后面的30 000~32 767之间,通过取模再加1得到的数在1~2768之间。
也就是说,如果我们利用这个函数试图产生一个范围在1~30 000之间的随机数时,前2768个值出现的概率是后面那些值出现概率的两倍。
前2768个值(1~2768)的概率相等,为:2/32 768.
后面值(2769~30 000)的概率为:1/32 768.
这种误差就大了。
正确的代码为:
程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define  MAX  (int) ((((long)RAND_MAX+1)/6)*6-1)

int fun_throw(void)
{//local declarations
 static int is_seeded=0;

 int value;


 //statements


 if(!is_seeded)

 {
  is_seeded=1;
  srand(time(NULL));

 }  //if

do
{
    value=rand();

 }
while(value>MAX);

return   value%6+1;
}  //fun_throw

int main()
{
  //local declarations 
    int num;
    int i;

 
  //statements    
 printf("请输入要投掷的次数:");

 scanf("%d",&num);

 printf("\n");

 for(i=0;i<num;i++)
     printf("%6d\n",fun_throw());

 return  0;
}  //main
搜索更多相关主题的帖子: color 
2011-04-21 19:56
帅的让人抽
Rank: 4
来 自:安徽
等 级:业余侠客
帖 子:94
专家分:224
注 册:2010-9-30
收藏
得分:0 
回复 2楼 voidx
随机抽牌问题……

樱花下落的速度依然是秒速五厘米,即使发了一千次短信,
心与心之间也只能靠近一厘米……
2011-04-21 20:02
帅的让人抽
Rank: 4
来 自:安徽
等 级:业余侠客
帖 子:94
专家分:224
注 册:2010-9-30
收藏
得分:0 
回复 6楼 waterstar
用时间做种子时,每次产生的随机序列是不相同的。如果不用随机种子函数或者用一个常数作为随机种子,那么每次程序运行时产生的随机序列是相同的。
程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void)

{  //statements
        srand(11);
        printf("%d\n",rand());
        printf("%d\n",rand());
        printf("%d\n",rand());
        return  0;
} //main

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void)

{  //statements
        srand(time(NULL));
        printf("%d\n",rand());
        printf("%d\n",rand());
        printf("%d\n",rand());
        return  0;
}

樱花下落的速度依然是秒速五厘米,即使发了一千次短信,
心与心之间也只能靠近一厘米……
2011-04-22 11:37
帅的让人抽
Rank: 4
来 自:安徽
等 级:业余侠客
帖 子:94
专家分:224
注 册:2010-9-30
收藏
得分:0 
回复 4楼 pangding
那随机抽牌洗牌问题该怎样解释……

樱花下落的速度依然是秒速五厘米,即使发了一千次短信,
心与心之间也只能靠近一厘米……
2011-04-22 11:40
快速回复:随机函数之等概率问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029877 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved