random()随机数的产生方式与原理
计算机中的随机数都是伪随机数
下面看这样一个C程序:
// rand_1.cpp
#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];
}
void main()
{unsigned int i,n;random_start();for(i=0;i<10;i++)printf("#u\t",random());printf("\n");
}
它完整地阐述了随机数产生的过程:
首先,
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。
其次,
RAND_SEED=(RAND_SEED*123+59)%65536;
是用来计算随机数的方法,随机数的计算方法在不同的计算机中是不同的,即使在相同的计算机中安装的不同的操作系统中也是不同的。我在linux和windows下分别试过,相同的随机种子在这两种操作系统中生成的随机数是不同的,这说明它们的计算方法不同。
然后,
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
随机种子为什么要在内存的0040:006CH处取?0040:006CH处存放的是什么?
学过《计算机组成原理与接口技术》这门课的人可能会记得在编制ROM BIOS时钟中断服务程序时会用到Intel 8253定时/计数器,它与Intel 8259中断芯片的通信使得中断服务程序得以运转,主板每秒产生的18.2次中断正是处理器根据定时/记数器值控制中断芯片产生的。在我们计算机的主机板上都会有这样一个定时/记数器用来计算当前系统时间,每过一个时钟信号周期都会使记数器加一,而这个记数器的值存放在哪儿呢?没错,就在内存的0040:006CH处,其实这一段内存空间是这样定义的:
TIMER_LOW DW ? ;地址为 0040:006CH
TIMER_HIGH DW ? ;地址为 0040:006EH
TIMER_OFT DB ? ;地址为 0040:0070H
时钟中断服务程序中,每当TIMER_LOW转满时,此时,记数器也会转满,记数器的值归零,即TIMER_LOW处的16位二进制归零,而TIMER_HIGH加一。rand01.c中的
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
正是把TIMER_LOW和TIMER_HIGH两个16位二进制数放进temp数组,再送往RAND_SEED,从而获得了“随机种子”。
现在,可以确定的一点是,随机种子来自系统时钟,确切地说,是来自计算机主板上的定时/计数器在内存中的记数值。
EN...没有最后。。lvl--
再看一段代码:
//rand_2.cpp
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{srand((unsigned)time(NULL));unsigned int r=rand();cout<<"r = "<<r<<endl; //根据C++ 98标准,可以不用return语句来介绍main函数return 0;
}
这里用户和其他程序没有设定随机种子,则使用系统定时/计数器的值做为随机种子,所以,在相同的平台环境下,编译生成exe后,每次运行它,显示的随机数会是伪随机数,即每次运行显示的结果会有不同。
总结
随机数是由随机种子根据一定的计算方法计算出来的数值。所以,只要计算方法一定,随机种子一定,那么产生的随机数就不会变。在相同的平台环境下,编译生成exe后,每次运行它,显示的随机数都是一样的。这是因为在相同的编译平台环境下,由随机种子生成随机数的计算方法都是一样的,再加上随机种子一样,所以产生的随机数就是一样的。
只要用户或第三方不设置随机种子,那么在默认情况下随机种子来自系统时钟(即定时/计数器的值)
random()随机数的产生方式与原理相关推荐
- Java生成随机数原理_Java中随机数的产生方式与原理详解
Java中随机数的产生方式与原理 查阅随机数相关资料,特做整理 首先说一下java中产生随机数的几种方式 在j2se中我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0- ...
- 1.24 Java周末总结 ①乘法数据的溢出 ②测试random随机数几率是否相等 ③判断字符串是否为纯数字...
一.乘法数据的溢出 背景:在算阶乘时,当数字太大后,结果为0,此时引出了数据在算乘法时数据的溢出 10!或者100! byte 8位 8! = -27=-128 (转换到byte允许数据范围内) ...
- Python攻城师的成长————模块突破(collections、time与datetime、random随机数模块)
今日学习目标: 学习并应用collections.time与datetime.random随机数模块知识 今日学习内容: collections模块 time与datetime模块 random随机数 ...
- java 随机句子_Java基础三(Scanner键盘输入、Random随机数、流程控制语句)
1.引用类型变量的创建及使用 2.流程控制语句之选择语句 3.流程控制语句之循环语句 4.循环高级 ###01创建引用类型变量公式 * A: 创建引用类型变量公式 * a: 我们要学的Scanner类 ...
- 【C++】random随机数与【C++11】/rand()和srand()的用法
文章目录 随机数 1. c++ 11 random随机数的使用(推荐使用) 1.1 1.2 1.3 1.4 2.1 C++中随机函数rand()和srand()的用法(老本版) 2.2 限制随机数的范 ...
- c库的rand/random随机数产生函数性能差?
有网文称c标准库的rand/random随机数产生函数性能极差.一直信以为真,但从没做过验证.最近因其他因缘,写了些代码专门验证rand/random的性能.结果大出意料,颠覆之前的成见. 结论如下: ...
- Java 常用类库 之 Random 随机数类实例
http://www.verejava.com/?id=169931132381103 /**知识点:Random 随机数类洗牌 */ import java.util.*;public class ...
- 单片机复位后为什么要对sp重新赋值_常见的单片机复位方式及其原理分析
为确保设计出的电路系统稳定可靠的工作,必须在电路中加入复位电路--将电路恢复到初始状态.类似于我们使用的电脑,一旦我们电脑死机或发生其他问题,我们会利用重启按钮重启我们的电脑.复位电路亦是如此,一旦我 ...
- stm32如何执行软复位_常见的单片机复位方式及其原理分析
为确保设计出的电路系统稳定可靠的工作,必须在电路中加入复位电路--将电路恢复到初始状态.类似于我们使用的电脑,一旦我们电脑死机或发生其他问题,我们会利用重启按钮重启我们的电脑.复位电路亦是如此,一旦我 ...
最新文章
- 开源企业IM,免费企业即时通讯软件-ENTBOOST云通讯平台Windows(r174)版本号公布...
- 教师节,收到学生的礼物和祝福,开心
- java并发问题_并发理论基础:并发问题产生的三大根源
- 【软件质量】代码注释的消极作用
- 巴赛尔协议与贷款产品利率解析
- 整理总结:深入浅出统计学 —— 卡方分布
- Excel2016保存文件闪退(在安装了Visio后)
- 罗马音平假字复制_罗马音游戏id可复制app下载-罗马音大全可复制v2.1 免费版-速游网...
- matlab中怎么求矩阵的转置
- UltraISO制作启动盘时报错:磁盘/映像容量太小
- 智慧工厂数字孪生建设方案
- echarts全国各市地图坐标
- 如何简单快速的写出幸运转盘抽奖
- MATLAB绘制垂直正态分布密度曲线
- Hadoop相关概念
- centos下Intel核显应用ffmpeg的qsv插件编解码
- 服务器的ip端口加密协议混淆,Obfsproxy - 混淆/加密端口数据
- 让你在[三分钟自我介绍]中突出自我
- seafile-搭建自己的私有云盘
- 我觉得吧学计算机也没,“其实我觉得吧,学我们艺术专业压力也没那么大!”...