【问题标题】:C++ rand() always giving same TWO values... and then working perfectlyC++ rand() 总是给出相同的两个值......然后完美地工作
【发布时间】:2020-12-07 06:06:49
【问题描述】:

首先,我知道播种时间种子的基本原理,我的程序的输出是部分随机的。但这让我很困惑。

在程序的后续执行中,七个随机生成的值可能如下所示:

14 14 47 70 84 2 24

14 28 42 52 31 10 12

63 25 4 50 20 27 56

63 19 55 44 65 60 52

14 16 17 40 54 77 4

63 6 79 36 51 85 39

其余的值看起来是随机的,但第一个值始终是 14 或 63。为什么会发生这种情况,我怎样才能让它完全随机?

该代码应该绘制一个随机的 Scrabble 字母而无需替换,并添加了一个 cout 语句用于调试目的。

#include <iostream>
using namespace std;

int main()
{
    string bag = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOOPPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ";

    srand(time(0));
    for (int a = 0; a < 7; a++)
    {
        int i = rand()%bag.size();
        cout << i << ' ';
        bag.erase(i,1);
    }
    cout << endl;
    return 0;
}
  • 在 MacOS Catalina 10.15 终端中编译
  • 配置为:--prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
  • Apple clang 版本 11.0.0 (clang-1100.0.33.17)
  • 目标:x86_64-apple-darwin19.6.0
  • 线程模型:posix

【问题讨论】:

  • 请发送minimal reproducible example。看来您可以将 Player::letter 中的代码移动到 main 并仍然重现该行为。
  • 我无法重现该行为。我得到随机的数字。您能否添加有关您正在使用的编译器以及编译命令的详细信息?
  • 你连续执行程序的速度有多快?如果你做的很快,你可能有第一个数字是相同的,因为 srand(time(0)) 还没有播种不同的值。如果您在每次执行后等待 1 或 2 秒,我每次都有漂亮的随机数
  • rand 远非最好的随机数生成器。实际上,这可能非常糟糕。 Here is a presentation on how bad and some better alternatives.
  • @S.M.新输出:1607326196 63 77 56 91 1 78 52; 1607326199 14 3 69 81 8 36 0; 1607326201 14 94 24 75 53 69 88; 1607326203 14 88 44 69 4 10 84; 1607326204 63 85 6 67 87 27 36

标签: c++ random


【解决方案1】:

rand()std::rand() 永远不会生成 true 随机数。它生成伪随机数。这是因为计算机本身无法生成真正的随机数,它需要帮助。假设您在上一次按键后恰好 2.054 秒按下了一个键。这确实是一个随机数。计算机使用这些数据来生成真正的随机数。 rand()std::rand() 生成一个伪随机数,因此需要播种(使用srand()std::srand())。如果您用来播种的数字不是随机的,那么输出也不会是随机的。此外,您正在使用time()(或std::time()),它返回一个int,其中包含自纪元以来经过的秒数。因此,如果您以太快的速度多次执行该程序,那么种子和输出将是相同的。您的标准库似乎也是一个糟糕的rand()std::rand() 函数。

示例:

程序的输出(从您的代码编译)快速执行 10 次(环境:Ubuntu,bash):

$ for i in {0..9} ; do ./a.out ; done
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42

怎么办?

我可以建议您使用另一个时间函数来播种,它以毫秒(甚至纳秒)为单位输出时间,或者使用您自己的随机数生成器。请参阅this article 了解伪随机数生成器的工作原理。这也将帮助您构建自己的标准库,因为您的标准库似乎提供了错误的 rand()std::rand() 函数。

【讨论】:

  • 但是OP的输出序列明显不同,除了第一个数字。
  • @AsteroidsWithWings 也许 OP 在这种情况下巧合地(或以编程方式)执行程序,此时输出是这样的。
  • 你知道每次发生这种情况的几率吗?
  • @AsteroidsWithWings 我不知道,但可以使用正确的算法来做到这一点。可能 OP 系统的 C 或者 C++ 有 bug。
  • 我记得听说过,但不记得遇到过 rand 必须丢弃第一个值的实现。
猜你喜欢
  • 1970-01-01
  • 2011-03-31
  • 2013-03-11
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 2015-06-23
  • 2020-07-23
相关资源
最近更新 更多