C++-随机数的产生
一、随机数
以前学C语言的时候感觉随机数没啥用的,现在想想是自己无知啦,在帮人做一个项目的时候发现随机数还是相当有用的,我们可以利用随机数来生成大量的测试数据。
有两种方法可以让你的程序每次运行结果不同:
1.让用户输入不同的数据(或者从文件中读取不同的数据);
2.对用户输入的相同数据采取不同的处理方式,使其运行结果不同。
大多数情况下,第一种方法是非常好的,用户总是希望他们程序的结果是可预测的。比如当编写一个文本编辑器或者网页浏览器时,你会希望程序在用户每次输入一段文本或网址时执行同样的操作,而不是由浏览器随机决定访问哪个页面,除非是使用StumbleUpon1。
1StumbleUpon是一个能让你“偶遇”有趣网页的网站:http://www.stumbleupon.com/。
但在某些情况,每次执行相同操作并不是一个好的处理方式。例如,很多电脑游戏依赖随机,俄罗斯方块便是一个典型的例子,如果每次游戏方块的下落顺序都相同,用户便会记住下落顺序,因为可以预测接下来会出现什么方块,所以得分会一次比一次高。最后游戏和背诵圆周率的千位小数没啥不同。为了让俄罗斯方块游戏更有意思,程序需要随机选择下一次方块的形状和朝向。
为了实现这个功能,计算机需要生成随机数。因为计算机会准确执行命令,当我们执行相同的操作时计算机总会返回同样的结果。这就很难生成真正的随机数。不过没有必要生成真的随机数。生成像随机数的数也能达到目的,这就是伪随机数。
要生成伪随机数,计算机需要一个种子,利用数学变换将种子转换成另一个值。新值再成为下一个种子。如果程序每次采用不同的种子,程序便永远不会生成相同的数据序列。这里使用的数学转换需要特别挑选,要让所有数字的生成概率相等但又不会有明显的计算模型。(例如,它不会只是每次对数字加1。)
C++提供了所有的功能。你无需关心数学转换,C++中有相关的函数实现。所有你要做的只是提供随机种子,使用当前时间作种子即可。让我们看一下细节:
1.1 随机数的产生
C++有两个函数,一个是设置随机种子,另一个是用种子产生随机数:
void srand (int seed);
srand函数将某个数字设置为种子。在程序开头处需要调用一次srand。使用srand的典型方法是把time函数的结果作为参数,time函数返回一个代表当前时间的数值。
time函数返回从1970年1月1日起到现在的秒数。这个规则源自于Unix操作系统,有时它称为Unix time。大多数情况下,时间存储在32位有符号整型中。
随着时间的增加,秒数会超过整型可表示的范围,最后将以负数结尾表示过去的时间。超过整型数的现象将发生在2038年,它引起了对“2038年问题”(Year2038 Problem)的讨论,使用Unix time的计算机程序将会把2038年当做1901年处理。详情请参考:
http://en.wikipedia.org/wiki/Year_2038_problem。
srand ( time ( NULL ) );
目前你不用了解NULL参数,先就照着这么写;
如果连续调用srand,程序会反复地更新随机数发生器种子,因为连续调用的时间序列非常相近,生成的随机数也会很相近。(使用srand必须包含cstdlib头文件,使用time函数必须包含ctime头文件。
#include <cstdlib>
#include <ctime>
int main ()
{
//在最开始处调用一次
srand( time( NULL ) );
}
参照下面原型调用rand函数来获取随机数。
int rand ();
注意rand函数没有任何参数,仅有一个返回值。让我们将返回值输出出来。
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int main ()
{
//在最开始处调用一次
srand( time( NULL ) );
cout << rand() << '\n';
}
C++有一个返回除法余数的操作符(如4/3商为1,余数为1)——模数运算符。如果你没有注意到也不要紧,人们总是自动屏蔽数学函数。但模数非常有用。因为被4整除的余数的范围是0~3。如果用rand函数返回的随机数除以所需数字的范围长度(即范围内数的数量),便会获得0到最大范围之间的值(不包含最大值)。
#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;
int randRange (int low, int high)
{
//先获取随机数,再处理得到从0到所需数字范围长度的值,然后加上最小值
return rand() % ( high - low + ) + low;
}
int main ()
{
srand( time( NULL ) );
for ( int i = ; i < ; ++i )
{
cout << randRange( , ) << '\n';
}
}
这段程序有两点需要注意的地方。首先,我们必须对high-low加1,举例说明原因,设想目标范围是0到10,当中有11种可能出现的值。减法获得的是两个值之间的差值,比范围内值的数量少1,因此必须加1。其次,注意我们需要加上目标范围的最小值,设想如果想获取10到20之间的数,通过上面的方法只能获取0到10之间的随机数,再加10才能将范围设定到10到20之间。
参考文献:c++现代程序设计方法
小结:
-我们产生随机数不用自己去编写数学变换公式,直接调用两个随机函数
-time(NULL)返回当前距离1970年的秒数,将其作为参数传递给srand生成随机种子;
-rand()生成随机数,无形参,每调用一次返回值一个
C++-随机数的产生的更多相关文章
- .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
.Net中我们通常使用Random类生成随机数,在一些场景下,我却发现Random生成的随机数并不可靠,在下面的例子中我们通过循环随机生成10个随机数: ; i < ; i++) { Rando ...
- DotNet生成随机数的一些方法
在项目开发中,一般都会使用到“随机数”,但是在DotNet中的随机数并非真正的随机数,可在一些情况下生成重复的数字,现在总结一下在项目中生成随机数的方法. 1.随机布尔值: /// <summa ...
- JavaScript 随机数
JavaScript内置函数random(seed)可以产生[0,1)之间的随机数,若想要生成其它范围的随机数该如何做呢? 生成任意范围的随机数 //生成[100,120)之间的随机数 Math.fl ...
- SQL Server 随机数,随机区间,随机抽取数据rand(),floor(),ceiling(),round(),newid()函数等
在查询分析器中执行:select rand(),可以看到结果会是类似于这样的随机小数:0.36361513486289558,像这样的小数在实际应用中用得不多,一般要取随机数都会取随机整数.那就看下面 ...
- 随机数(random)
需求 Random rd=new Random(); 需要十以内的随机数 (0---10) System.out.println((int)((rd.nextDouble()*100)/10)); ...
- [LeetCode] Insert Delete GetRandom O(1) 常数时间内插入删除和获得随机数
Design a data structure that supports all following operations in average O(1) time. insert(val): In ...
- Python 随机数用法
1. random.seed(int) 给随机数对象一个种子值,用于产生随机序列. 对于同一个种子值的输入,之后产生的随机数序列也一样. 通常是把时间秒数等变化值作为种子值,达到每次运行产生的随机系列 ...
- C语言产生标准正态分布或高斯分布随机数
C语言 产生标准正态分布或高斯分布 随机数 产生正态分布或高斯分布的三种方法: 1. 运用中心极限定理(大数定理) #include #include #define NSUM 25 double g ...
- C语言基础(11)-随机数发生器
一. rand() rand是一个C语言库函数,功能是生成一个随机数.rand需要一个不同的种子,才能生成不同的随机数. 二. srand(int seed) rand需要一个不同的种子,才能生成不同 ...
- shell 指定范围产生随机数
#/bin/bash echo "---------------产生随机数---------------" read -p "请输入起始数:" a read - ...
随机推荐
- EasyUI笔记(四)菜单和按钮
本系列只列出一些常用的属性.事件或方法,具体完整知识请查看API文档 Menu(菜单) 菜单组件通常用于快捷菜单.他是构建其他菜单组件的必备基础组件.比如:menubutton和splitbutton ...
- BZOJ #2506. calc [根号分治,莫队,二分]
\(p\) 是个正常范围, \(\sqrt p <= 100\) 比较小,预处理出来 \(a_i % p == k\) 的位置,然后丢进去,最后询问的 \(p\) 如果大于 \(100\) 就莫 ...
- 吴裕雄--天生自然HADOOP操作实验学习笔记:hbase微博案例
实验目的 熟悉hbase表格设计的方法 熟悉hbase的javaAPI 通过API理解掌握hbase的数据的逻辑视图 了解MVC的服务端设计方式 实验原理 上次我们已经初步设计了学生选课案例的,具体功 ...
- 吴裕雄--天生自然HADOOP操作实验学习笔记:tf-idf算法
实验目的 通过实验了解tf-idf算法原理 通过实验了解mapreduce的更多组件 学会自定义分区,读写缓存文件 了解mapreduce程序的设计方法 实验原理 1.TF-IDF简介 TF-IDF( ...
- Python 一键安装全部依赖包
使用 pip requirements.txt 用来记录项目所有的依赖包和版本号,只需要一个简单的 pip 命令就能完成. pip freeze > requirements.txt 生成的文件 ...
- 【BZOJ 1022】 [SHOI2008]小约翰的游戏John(Anti_SG)
Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取 的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不 ...
- VS打包程序步骤
1.下载打包的程序 2.在你的程序里面安装打包的项目 3.添加项目输出 4.为项目添加必要的文件 双击前面建立好的主输出 一般文件为一些配置文件(如使用Nlog写日志,需要添加Nlog的配置文件)和图 ...
- 【LInux01】学习Linux课程体系
知识 =>技能 需要大量的练习 相当于复盘 要有成就感 在一个领域深挖,再迁移到其他领域 1.两周以后的知识留存率: 主动学习: 动手实践:40% 讲给别人听:70% 写博客:是写教程,便 ...
- vue 查看dist文件里的结构
场景:优化打包后的代码,提高性能. 1.方式一:report-json. 1.1 package.json文件里加入以下命令, "report": "vue-cli-se ...
- Common Subsequence POJ - 1458 最长公共子序列 线性DP
#include <iostream> #include <algorithm> #include <string> #include <cstring> ...