rand()详解以及srand((unsigned)time(NULL))放在循环体内的结果分析

起因:在IFS画分形的循环中使用了srand((unsigned)time(NULL));
运行:循环一万次的函数并未达到分形图形的效果
找错中…
解决:将srand((unsigned)time(NULL));从循环中移除就画出来了!

发现自己对srand( ),rand( )一无所知…
那就赶紧补习呗!

一.
rand( ):产生一个随机数

返回一个介于0RAND_MAX之间的伪随机整数。

这个数字是由一个算法生成的,该算法在每次调用时返回一系列显式不相关的数字。该算法使用一个种子seed来生成序列,该序列应该使用函数**srand( )**初始化为某个特定的值。
每次的随机数种子一样,则rand()的值就一样。

【为什么说是伪随机数呢】

解答:数学上产生的都是伪随机数,真正的随机数使用物理方法产生的。伪随机就是在相同条件下,能重复生成的。

【计算机是如何产生伪随机数的呢?】

解答:来源于百度百科

#include <stdlib.h>
static unsigned int RAND_SEED;
unsigned int random(void)
{
    RAND_SEED=(RAND_SEED*123+59)%65536;
    return(RAND_SEED);
}
void random_start(void)
{
    int temp[2];
    movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
    RAND_SEED=temp[0];
}
main()
{
    unsigned int i,n;
    random_start();
    for(i=0;i<10;i++)
        printf("%u\t",random());
    printf("\n");
}

(一)random_start( ):
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
这个函数用来移动内存数据,其中FP_SEG(far pointer to segment)是取temp数组段地址的函数,FP_OFF(far pointer to offset)是取temp数组相对地址的函数,movedata函数的作用是把位于0040:006CH存储单元中的双字节放到数组temp的声明的两个存储单元中。这样可以通过temp数组把0040:006CH处的一个16位的数送给RAND_SEED。

【为什么是0040:006CH处呢】

编制ROM BIOS时钟中断服务程序时会用到Intel 8253定时/计数器,它与Intel 8259中断芯片的通信使得中断服务程序得以运转,主板每秒产生的18.2次中断正是处理器根据定时/记数器值控制中断芯片产生的。在计算机的主机板上都会有这样一个定时/记数器用来计算当前系统时间,每过一个时钟信号周期都会使记数器加1,而这个记数器的值就存放在内存的0040:006CH处,其实这一段内存空间是这样定义的:

TIMER_LOW DW ? ;地址为 0040:006CH
TIMER_HIGH DW ? ;地址为 0040:006EH
TIMER_OFT DB ? ;地址为 0040:0070H

时钟中断服务程序中,每当TIMER_LOW转满时,此时,记数器也会转满,记数器的值归零,即TIMER_LOW处的16位二进制归零,而TIMER_HIGH加1。
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
正是把TIMER_LOW和TIMER_HIGH两个16位二进制数放进temp数组,再送往RAND_SEED,从而获得了“随机种子”。

可以确定的一点是,随机种子来自系统时钟,确切地说,是来自计算机主板上的定时/计数器在内存中的记数值。

(二)random( ):RAND_SEED=(RAND_SEED*123+59)%65536; 这是用来计算随机数的方法,随机数的计算方法在不同的计算机中是不同的,即使在相同的计算机中安装的不同的操作系统中也是不同的。

【有哪些算法生成伪随机数呢】

  • 线性同余法
  • 梅森旋转法
  • 平方取中法
  • Lagged Fibonacci generator

二.需要明确的是:
(一)计算方法一定,随机种子一定,产生的随机数就不会变。

(二)srand((unsigned)time(NULL));这条语句是使用当前时间(以秒为单位,一秒钟数字增加一个)作为种子,则种子为一个不固定的数, 则产生的随机数每次执行都不一样。
代码a:

int main(){
	srand((unsigned)time(NULL));
	for(int i=0;i<5;i++){	
		printf("%d\n",rand()%100+1);
	}
	return 0;
}

执行代码a:得到五个不同的数字。

代码b:

int main(){
	for(int i=0;i<5;i++){
		srand((unsigned)time(NULL));
		printf("%d\n",rand()%100+1);
	}
	return 0;
}

执行代码b:会得到五个相同数字重复的结果,为什么呢?因为time只能达到s(秒)级精度,而如果计算机可以在一秒钟内处理这五个循环迭代(速度比较快),自然每次产生的随机数都一样。这也解释了我遇到的问题!

因此如果想在一个程序中生成随机数序列,需要至多在生成随机数之前设置一次随机种子。 即:只需在主程序开始处调用srand((unsigned)time(NULL)); 后面直接用rand就可以。不要在for等循环放置srand((unsigned)time(NULL));

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值