rand随机函数的工作原理?迷茫?

xuzhidiao 2009-09-27 04:27:18
偶然情况下,在VC6.0下用了rand函数,发现一些不解的问题。
即用了srand时间种子,中间间隔一秒
包含3个头文件
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

自己做个按钮和3个显示框
代码大致如下
void hello::OnButtonTime1()
{CString str2,str3,str4;
float kop,bk=0,lk=0;
int i,n;
line1:
kop=bk+lk;
if(kop==0) goto line2;
///显示运作总数
str2.Format("%.f",kop);
SetDlgItemText(IDC_EDIT1,str2);
///显示出现0概率
str3.Format("%.2f",bk/kop);
SetDlgItemText(IDC_EDIT2,str3);
///显示出现1概率
str4.Format("%.2f",lk/kop);
SetDlgItemText(IDC_EDIT3,str4);
UpdateWindow();
line2:Sleep(1000);
srand(time(NULL));
for(i=0;i<10;i++)
{n=rand()%2;}
if(n==0) {bk=bk+1;Sleep(30000);goto line1;}
if(n==1) {lk=lk+1;Sleep(15000);goto line1;}
}


约20秒好像是个分水点,假如一个都在20秒以上如Sleep(60000),Sleep(30000)概率是一样的,假如一个在20多秒以上,一个在20多秒以下(比如Sleep(30000) vs Sleep(1000)或Sleep(3000)),就会出现概率偏差,假如都在20多秒以下,概率又差不多。
假如记录0的次数,发现出现0的次数很多,之后才出现几个1,不断重复
照理说概率是50%对50%(假如是50%对50%,得出的0和1是呈规则排列的 即多少次(好像4次)0后出现1,1出现多少次(同样好像4此)后又出现0,不断重复,这可能是rand运用线性同余法的缺陷,或主板计数器/定时器本身就这样的问题,或机器的算法问题)
但多次(越多越好)后得出的结果是Sleep(30000)概率为80%~85%左右(放到n==1也一样)(假如我在0 1里面放一些不同程序,运行时间不一样,差别更大,可达到90%对10%或10%对90%;但把Sleep(30000)改成Sleep(15000)或把Sleep(15000)改成Sleep(30000)后,概率就恢复50%了,这是怎么回事?伪随机函数是依靠主板的计数器(是8253计数器/定时器吗,我不知道)来运作的,每秒中断18.2次,即约55ms更新一次时间,请教高人,解释下rand到底是怎么运作的,以上Sleep(30000)和Sleep(15000)的概率为什么不一样。

你可看kop的值,可运行50次,100次,500次,概率偏差是不会变的。

希望大家集思广益,帮我想想为什么。谢谢
...全文
274 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
用户 昵称 2009-09-27
  • 打赏
  • 举报
回复
用c的随机数做种子,生成伪随机数就行了。
weiym 2009-09-27
  • 打赏
  • 举报
回复
为什么不自己看下CRT的源代码呢
#ifndef _MT
static long holdrand = 1L;
#endif /* _MT */

/***
*void srand(seed) - seed the random number generator
*
*Purpose:
* Seeds the random number generator with the int given. Adapted from the
* BASIC random number generator.
*
*Entry:
* unsigned seed - seed to seed rand # generator with
*
*Exit:
* None.
*
*Exceptions:
*
*******************************************************************************/

void __cdecl srand (
unsigned int seed
)
{
#ifdef _MT

_getptd()->_holdrand = (unsigned long)seed;

#else /* _MT */
holdrand = (long)seed;
#endif /* _MT */
}


/***
*int rand() - returns a random number
*
*Purpose:
* returns a pseudo-random number 0 through 32767.
*
*Entry:
* None.
*
*Exit:
* Returns a pseudo-random number 0 through 32767.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl rand (
void
)
{
#ifdef _MT

_ptiddata ptd = _getptd();

return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );

#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧