伪随机数问题笔记
计算机中随机数由“随机种子”产生。“随机种子”是一个无符号整形数。以下程序阐述了随机数产生的过程:
#include
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。
random根据随机种子RAND_SEED的值计算出随机数:
RAND_SEED=(RAND_SEED*123+59)%65536;
关键点:随机种子为什么要在内存的0040:006CH处取?
计算机主机板上有一个定时/记数器用来计算当前系统时间,每过一个时钟信号周期记数器加 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 ,获得“随机种子”。
结论:随机种子来自系统时钟,来自计算机主板上的定时/计数器在内存中的记数值。
推论:1. 随机种子一定,产生的随机数不变。
#include
using namespace std;
int main()
{
unsigned int seed=930;
srand(seed);
cout<<rand()<<endl;
return 0;
}
2.设随机种子来自系统时钟,每次运行显示的结果会不同。
#include
using namespace std;
int main()
{
srand((unsigned)time(NULL));
cout<<rand()<<endl;
return 0;
}
这样的随机数要经过改造才能用。
计算机中随机数由“随机种子”产生。“随机种子”是一个无符号整形数。以下程序阐述了随机数产生的过程:
#include
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。
random根据随机种子RAND_SEED的值计算出随机数:
RAND_SEED=(RAND_SEED*123+59)%65536;
关键点:随机种子为什么要在内存的0040:006CH处取?
计算机主机板上有一个定时/记数器用来计算当前系统时间,每过一个时钟信号周期记数器加 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 ,获得“随机种子”。
结论:随机种子来自系统时钟,来自计算机主板上的定时/计数器在内存中的记数值。
推论:1. 随机种子一定,产生的随机数不变。
#include
using namespace std;
int main()
{
unsigned int seed=930;
srand(seed);
cout<<rand()<<endl;
return 0;
}
2.设随机种子来自系统时钟,每次运行显示的结果会不同。
#include
using namespace std;
int main()
{
srand((unsigned)time(NULL));
cout<<rand()<<endl;
return 0;
}
这样的随机数要经过改造才能用。