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()生成随机数,无形参,每调用一次返回值一个

  • 相关阅读:
    什么是模板方法模式?
    在多线程环境下,SimpleDateFormat 是线程安全的吗?
    抽象类是什么?它与接口有什么区别?你为什么要使用过 抽象类?
    依赖注入和工程模式之间有什么不同?
    什么时候使用访问者模式?
    Java 中,受检查异常 和 不受检查异常的区别?
    说出 5 个 JDK 1.8 引入的新特性?
    什么是领域驱动设计?
    列举 IoC 的一些好处?
    什么是 Spring 配置文件?
  • 原文地址:https://www.cnblogs.com/lemaden/p/10149444.html
Copyright © 2011-2022 走看看