【问题标题】:Rand() seems to not work properly [duplicate]Rand() 似乎无法正常工作[重复]
【发布时间】:2012-09-10 02:50:04
【问题描述】:

可能重复:
Why do I always get the same sequence of random numbers with rand()?

我一直在尝试在 C 中生成随机数,但遇到了一些奇怪的事情。我不知道它是否仅在我的编译器上,但每当我尝试使用 rand() 函数生成伪随机数时,它都会返回一个非常可预测的数字——确切地说是使用之前的参数生成的数字加上 3.125。很难解释,但这里有一个例子。

srand(71);
int number = rand();
printf("%d", number);

这将返回 270。

srand(72);
int number = rand();
printf("%d", number);

这将返回 273。

srand(73);
int number = rand();
printf("%d", number);

这将返回 277。

srand(74);
int number = rand();
printf("%d", number);

这将返回 280。

每八分之一的数字高 4。否则为 3。

这不可能是对的。我的编译器有问题吗?

编辑:我想通了——我创建了一个函数,我只播种一次,然后我循环 rand() 并生成随机数。谢谢大家!

【问题讨论】:

  • 这里唯一的错误是您对播种的理解。播种一次,不再播种。
  • rand 在很多方面都很糟糕,这就是其中之一。

标签: c random srand


【解决方案1】:

每次调用rand() 都会返回预定义序列中的下一个数字,其中起始数字是提供给srand() 的种子。这就是为什么它被称为 -随机数生成器,而不是随机数生成器。

【讨论】:

    【解决方案2】:

    这里的困惑在于伪随机数生成器的工作原理。

    像 C 的 rand 这样的伪随机数生成器通过一个代表当前“状态”的数字来工作。每次调用rand 函数时,都会对“状态”编号进行一些确定性计算,以生成下一个“状态”编号。因此,如果为生成器提供相同的输入(相同的“状态”),它将产生相同的输出。

    因此,当您使用srand(74) 为生成器播种时,它每次都会生成相同的数字字符串。当您使用srand(75) 为生成器播种时,它将生成不同的数字字符串等。

    确保每次输出不同的常用方法是始终提供不同的种子,通常通过以秒/毫秒为单位的当前时间播种生成器来完成,例如srand(time(NULL)).

    编辑:这是一个演示此行为的 Python 会话。完全符合预期。

    >>> import random
    

    如果我们给生成器播种相同的数字,它总是会输出相同的序列:

    >>> random.seed(500)
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
    >>> random.seed(500)
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
    >>> random.seed(500)
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
    

    如果我们给它一个不同的种子,即使是稍微不同的种子,数字将与旧种子完全不同,但如果使用相同的(新)种子,数字仍然相同:

    >>> random.seed(501)
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
    >>> random.seed(501)
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
    >>> random.seed(501)
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
    

    我们如何让我们的程序每次都有不同的行为?如果我们提供相同的种子,它的行为总是相同的。我们可以使用time.time()函数,每次调用它都会产生不同的数字:

    >>> import time
    >>> time.time()
    1347917648.783
    >>> time.time()
    1347917649.734
    >>> time.time()
    1347917650.835
    

    因此,如果我们通过调用time.time() 继续重新播种它,我们每次都会得到不同的数字序列,因为种子每次都不同:

    >>> random.seed(time.time())
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [60, 75, 60, 26, 19, 70, 12, 87, 58, 2, 79, 74, 1, 79, 4, 39, 62, 20, 28, 19]
    >>> random.seed(time.time())
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [98, 45, 85, 1, 67, 25, 30, 88, 17, 93, 44, 17, 94, 23, 98, 32, 35, 90, 56, 35]
    >>> random.seed(time.time())
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [44, 17, 10, 98, 18, 6, 17, 15, 60, 83, 73, 67, 18, 2, 40, 76, 71, 63, 92, 5]
    

    当然,比不断地重新播种更好的是播种一次并从那里继续:

    >>> random.seed(time.time())
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [94, 80, 63, 66, 31, 94, 74, 15, 20, 29, 76, 90, 50, 84, 43, 79, 50, 18, 58, 15]
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [30, 53, 75, 19, 35, 11, 73, 88, 3, 67, 55, 43, 37, 91, 66, 0, 9, 4, 41, 49]
    >>> [random.randint(0, 100) for _ in xrange(20)]
    [69, 7, 25, 68, 39, 57, 72, 51, 33, 93, 81, 89, 44, 61, 78, 77, 43, 10, 33, 8]
    

    【讨论】:

      【解决方案3】:

      rand()pseudo random number generator 实现。

      连续调用rand()产生的数字分布具有随机数的性质,但顺序是预先确定的。 “开始”编号由您提供的种子决定。

      您应该只给 PRNG 一个种子。为其提供多个种子可以从根本上改变生成器的随机性。此外,一遍又一遍地为其提供相同的种子会消除所有随机性。

      【讨论】:

      • 你误会了,上面的四个代码片段不是同一个代码文件的一部分。
      • 其实我明白了;但是,关键是,如果您调用 seed 然后 rand 并多次执行,您不应该期望看到随机行为。如果您在调用种子后多次调用 rand,您只会观察到随机行为。
      【解决方案4】:

      不管实现如何,生成一个“随机”数字取决于divergent infinite sequence。无限序列是使用随机函数的种子生成的,由于其性质,它实际上是伪随机的。这将向您解释为什么您的数字实际上非常依赖于您提供函数的种子。

      在某些实现中,序列只有一个,而种子是序列的起始成员。在其他情况下,取决于种子,有不同的序列。如果未提供种子,则种子由内部“时钟”确定。

      通过分别执行randValue % upperBoundrandValue + lowerBound 对随机数使用上限和下限时,数字会被截断。随机实现与Hash Functions 非常相似。根据体系结构,随机值的上限取决于它可以执行的最大整数/双精度,如果用户没有设置较低的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-12
        • 1970-01-01
        • 2017-09-04
        • 2012-05-06
        • 2013-02-17
        • 2017-10-09
        • 2017-08-03
        相关资源
        最近更新 更多