zoukankan      html  css  js  c++  java
  • C++-随机数的产生

    一、随机数

      以前学C语言的时候感觉随机数没啥用的,现在想想是自己无知啦,在帮人做一个项目的时候发现随机数还是相当有用的,我们可以利用随机数来生成大量的测试数据。

      有两种方法可以让你的程序每次运行结果不同:

    1.让用户输入不同的数据(或者从文件中读取不同的数据);
    2.对用户输入的相同数据采取不同的处理方式,使其运行结果不同。

      大多数情况下,第一种方法是非常好的,用户总是希望他们程序的结果是可预测的。比如当编写一个文本编辑器或者网页浏览器时,你会希望程序在用户每次输入一段文本或网址时执行同样的操作,而不是由浏览器随机决定访问哪个页面,除非是使用StumbleUpon1。
    1StumbleUpon是一个能让你“偶遇”有趣网页的网站:http://www.stumbleupon.com/。

      但在某些情况,每次执行相同操作并不是一个好的处理方式。例如,很多电脑游戏依赖随机,俄罗斯方块便是一个典型的例子,如果每次游戏方块的下落顺序都相同,用户便会记住下落顺序,因为可以预测接下来会出现什么方块,所以得分会一次比一次高。最后游戏和背诵圆周率的千位小数没啥不同。为了让俄罗斯方块游戏更有意思,程序需要随机选择下一次方块的形状和朝向。

      为了实现这个功能,计算机需要生成随机数。因为计算机会准确执行命令,当我们执行相同的操作时计算机总会返回同样的结果。这就很难生成真正的随机数。不过没有必要生成真的随机数。生成像随机数的数也能达到目的,这就是伪随机数

      要生成伪随机数,计算机需要一个种子,利用数学变换将种子转换成另一个值。新值再成为下一个种子。如果程序每次采用不同的种子,程序便永远不会生成相同的数据序列。这里使用的数学转换需要特别挑选,要让所有数字的生成概率相等但又不会有明显的计算模型。(例如,它不会只是每次对数字加1。)

      C++提供了所有的功能。你无需关心数学转换,C++中有相关的函数实现。所有你要做的只是提供随机种子,使用当前时间作种子即可。让我们看一下细节:

    1.1 随机数的产生

      C++有两个函数,一个是设置随机种子,另一个是用种子产生随机数:

      

    1 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。

    1 srand ( time ( NULL ) );

      目前你不用了解NULL参数,先就照着这么写;

      如果连续调用srand,程序会反复地更新随机数发生器种子,因为连续调用的时间序列非常相近,生成的随机数也会很相近。(使用srand必须包含cstdlib头文件,使用time函数必须包含ctime头文件。
      

    1 #include <cstdlib>
    2 #include <ctime>
    3 int main ()
    4 {
    5   //在最开始处调用一次
    6   srand( time( NULL ) );
    7 }

      参照下面原型调用rand函数来获取随机数。

    1 int rand ();

      注意rand函数没有任何参数,仅有一个返回值。让我们将返回值输出出来。

     1 #include <cstdlib>
     2 #include <ctime>
     3 #include <iostream>
     4 using namespace std;
     5 int main ()
     6 {
     7   //在最开始处调用一次
     8   srand( time( NULL ) );
     9   cout << rand() << '
    ';
    10 }

      C++有一个返回除法余数的操作符(如4/3商为1,余数为1)——模数运算符。如果你没有注意到也不要紧,人们总是自动屏蔽数学函数。但模数非常有用。因为被4整除的余数的范围是0~3。如果用rand函数返回的随机数除以所需数字的范围长度(即范围内数的数量),便会获得0到最大范围之间的值(不包含最大值)。

     1 #include <ctime>
     2 #include <cstdlib>
     3 #include <iostream>
     4 using namespace std;
     5 int randRange (int low, int high)
     6 {
     7   //先获取随机数,再处理得到从0到所需数字范围长度的值,然后加上最小值
     8   return rand() % ( high - low + 1 ) + low;
     9 }
    10 int main ()
    11 {
    12   srand( time( NULL ) );
    13   for ( int i = 0; i < 1000; ++i )
    14   {
    15   cout << randRange( 4, 10 ) << '
    ';
    16   }
    17 }

      这段程序有两点需要注意的地方。首先,我们必须对high-low加1,举例说明原因,设想目标范围是0到10,当中有11种可能出现的值。减法获得的是两个值之间的差值,比范围内值的数量少1,因此必须加1。其次,注意我们需要加上目标范围的最小值,设想如果想获取10到20之间的数,通过上面的方法只能获取0到10之间的随机数,再加10才能将范围设定到10到20之间。

    参考文献:c++现代程序设计方法

    小结:

      -我们产生随机数不用自己去编写数学变换公式,直接调用两个随机函数

      -time(NULL)返回当前距离1970年的秒数,将其作为参数传递给srand生成随机种子;

      -rand()生成随机数,无形参,每调用一次返回值一个

  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/lemaden/p/10149444.html
Copyright © 2011-2022 走看看