【问题标题】:srand(time(0)) and random number generationsrand(time(0)) 和随机数生成
【发布时间】:2011-06-11 19:28:01
【问题描述】:
srand(time(0)) 

在 C++ 中用于帮助生成随机数,方法是为 rand 播种一个起始值。

但是,你能解释一下它到底是做什么的吗?

谢谢。

【问题讨论】:

    标签: c++ random


    【解决方案1】:

    srand() 给随机函数一个新的种子,一个起点(通常随机数是通过取前一个数(或种子)来计算的,然后对该数执行许多操作以生成下一个)。

    time(0) 给出了自 Unix 纪元以来的时间,以秒为单位,这是一个非常好的“不可预测”的种子(你可以保证你的种子只会相同一次,除非你在同一秒内多次启动你的程序)。

    【讨论】:

    • 它是否“相当好不可预测”取决于攻击者的手段。如果可以猜测随机数是何时生成的,那么可能的种子值空间可能非常短。因此,这不是一种生成加密安全随机数的方法。但是 srand/rand 无论如何都不适合这个...
    • 当你说:“time(0) 以秒为单位给出时间......”,你是什么意思?你能举一个输出的例子吗?谢谢。
    • Unix 纪元是 1970 年 1 月 1 日 00:00:00。 time(0) 返回从那一刻起经过的秒数。
    • "time(0) 返回从那一刻起经过的秒数。"。但是,不应该像你说的那样我以秒为单位获得时间吗?例如,今天是 2011 年 1 月 19 日。我应该期望 time(0) 为我返回什么?换句话说,假设现在是 2011 年 1 月 19 日下午 5:04,那么 time(0) 会(大约)给我什么?谢谢。
    • +1 表示“除非你在同一秒内多次启动程序”,我在一秒内多次 sranded(time(NULL)) => 因此总是相同的随机数:D跨度>
    【解决方案2】:

    据我所知,有一个方程式用于生成一系列值。下一个值在一定程度上受上一个值的影响。通过使用时间,您可以设置方程的初始值。请记住,这些值是伪随机的。

    例如,如果你这样做:

    srand(1); srand(1);

    将生成相同的数字序列。但是,如果你这样做:

    srand(time(0)); srand(time(0) + 1);

    由于种子值不同,会生成两个不同的数字序列。

    【讨论】:

    • 在最后一个示例中,除非两个 srand 调用之间的间隔超过 1 秒,否则并没有真正的不同。如果您在应用程序开始时有一次 srand(time(0)) 并且每秒运行多次(例如,某些脚本方法),则这种情况成立。有时可能会令人惊讶。
    • @Tomalak Gert'kal @Kos- 同意,这是一个我必须找到一次的讨厌的错误。在示例中,这些行的执行速度可能比相隔一秒快得多。更新了答案。
    • @user489041:你还不如现在写srand(1); srand(2);。 :P 你还应该提到,在一个程序中多次调用srand 通常是错误的;您的回答可能暗示语言新手他应该每秒srand
    • @Tomalak 同意,我绝不会推荐用于实际生产的代码。只是为了表明初始值会影响数字序列。
    【解决方案3】:

    C rand 函数使用种子生成随机数(就像大多数 -- 任何? -- 伪随机生成器一样)。

    srand 用于设置随机生成算法使用的种子。 time 返回的值(即:当前秒)通常被传递给这样的函数,因为它是最容易获取的值,通常在应用程序的两次执行之间是不同的

    【讨论】:

      【解决方案4】:

      首先,srand & rand 用于/来自 C,而不是 C++,C++0x 正在引入自己的random number generator classes

      除了srandrand 是实现定义的之外,它们只需要传递0 到RAND_MAX 之间的随机数。在windows 上,它是一个基本的MWC16/32,使用TLS 存储种子,srand 设置该种子,然后rand 使用该种子来滚动伪随机数。

      通过随机数生成器,它非常糟糕,尤其是 Windows 版本。

      【讨论】:

      • +1 关于安全性的要点。另请注意,至少在 ISO C 中 RAND_MAX 可能小到 32,768,因此它仅提供 15 位随机性,即使您使用完全随机的种子...
      【解决方案5】:

      有一个article at Wikipedia 提供了一些很好的历史和使用的算法示例。

      简短的版本是rand() 及其同类是伪随机数生成器。事实上,它们实际上是确定性的——产生的数字序列总是相同的。但是,序列非常长,播种机制提供了一种从序列中(或多或少)任意位置开始的方法。

      根据随机数的使用方式,有多种标准可用于评估伪随机生成器的质量。在非常简单的情况下,也许只需要从对rand() 的连续调用中重复值的概率很低。但是,您可能还希望这些数字符合特定的统计分布。 (据我所知,大多数 PRNG 会产生均匀分布的数字。但是存在各种函数或可以轻松编写以将其转换为高斯分布或您可能需要的任何其他函数。)

      最后,当考虑到安全性时,您需要一种算法,就所有实际目的而言,它是不可预测的。如果攻击者知道之前生成的数字,那么她应该无法预测下一个数字。在非常高安全性的应用程序中,可能会使用真正的随机数生成器;这些将依赖于各种外部随机源,例如无线电静电、图像捕获设备中的热噪声(镜头盖打开)或其他此类源。此外,许多现代操作系统(包括 Linux)从各种来源(例如不可预测的用户交互)收集和存储“熵池”,并允许从中生成随机数。

      不习惯使用伪随机生成器的人的一个常见编程错误是在每次调用 rand() 之前重新播种。当然,这是不必要的,而且可能是不可取的。每个生成器只播种一次。

      【讨论】:

        【解决方案6】:
        #include "stdio.h" //rmv coding for srand is pure
        #include "conio.h"
        #include "time.h"
        
        void main()
        {
        
            time_t t;
        
            srand(time(0));
        
            for (i = 1; i <= 10; i++) 
                cout << (unsigned) rand() % 1000 - 90 << "\t";
        
            for (i = 1; i <= 10; i++)
                cout << (char) rand() % 100 - 90 << "\t";
        
            getch();
        
        }
        

        【讨论】:

        • 这不是问题的答案,也不是有效的 C++ 代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-13
        • 1970-01-01
        • 1970-01-01
        • 2015-12-17
        • 1970-01-01
        相关资源
        最近更新 更多