在c ++中,在有和没有调试的情况下执行程序时,rand()会生成不同的结果

时间:2018-09-16 19:16:24

标签: c++

所以我一直在用c ++构建一个简单的控制台游戏,在这里我使用来自stdlib.h的rand()函数。我已经意识到,如果我在调试模式下执行程序或未进行调试,则可以从rand函数获得不同的结果。

这是我使用rand函数的代码:

void Game::SelectHiddenWord(Fstring &word) {
    std::vector<Fstring> WordList{ "plan","planet","planes","radios","gamers","images",
    "amigos","micros","macros","frogs","raids","roads","paris","smog","cars","macs","scam","some","farm","fair",
    "jam","rat","map","zig","zag","isogram","amorist","roaming","mirages","soaring","cargos","disarm","isobar"
};
    int32 Length = WordList.size();
    int32 randomNumber = std::rand()%Length;
    word = WordList.at(randomNumber);
}

因此,基本上,我有一个带有等距图的单词表,并且我正在使用rand函数生成一个整数,当从单词表中选择一个单词时,它将用作索引。我发现每次执行程序时,randomNumber整数始终为14,这将使我从单词表中看到单词“ smog”。首先,我认为这可能是一个错误,因为我已经阅读过rand()函数并不是生成随机数的最佳方法。所以我以调试模式启动程序,发现我的randomNumber整数现在是32,这将使我从单词表中获得“撤防”一词。每次我使用debugmode时都会发生这种情况。

因此,在没有调试的情况下启动时,我总是得到“烟雾”一词,在有调试的情况下启动时,总​​是得到“撤防”一词,所以我真的可以只玩两个单词。

那么这是rand()函数的某种错误,当它在调试模式下和没有调试模式下执行程序时,其行为会有所不同吗?

我正在尝试学习c ++,但是找不到有关rand函数的任何信息,因此我不知道该如何解决此问题。因此,如果你们中有人知道如何解决此问题,那么在我使用调试模式或不进行调试的情况下,rand()函数将表现相同并独立生成相同的数字。还是我需要使用另一个函数来生成我的随机数?

任何帮助将不胜感激!

编辑:

我不想知道为什么rand()函数每次都会生成相同的值。 当我在不调试的情况下启动程序时,rand()总是生成数字14,我希望这种情况发生。但是,如果我以调试模式启动程序,则rand()始终生成数字32。但是,如果我以调试模式执行程序或不进行调试,则我希望rand函数始终生成数字14。

所以问题在于,为什么在执行有或没有调试的情况下,rand()函数的行为会有所不同并生成不同的数字。我什至不知道是否有可能回答这个问题,也许这可能与我的机器有关。

我的测试代码:

void Game::Print() {
Fstring HIDDEN_WORD{}; //This MUST be an isogram
SelectHiddenWord(HIDDEN_WORD);

MyHiddenWord= HIDDEN_WORD;
std::cout << MyHiddenWord << std::endl; //This prints "smog" to the screen if I start the program without debugging, 
                                       //and if I debug the program it prints "disarm" to the screen

我的主要方法:

Game MyGame;
int main() {
 MyGame.Print();
}

我正在使用Microsoft Visual C ++编译器。

1 个答案:

答案 0 :(得分:0)

要解决为什么rand()在调试模式下行为不同的问题,这是编译器供应商的问题。它在内部的工作方式由实现定义(即取决于编译器的创建者)。来自cppreference

  

不能保证随机序列的质量   生产的。 [...]   对于严重的随机数生成需求,不建议使用rand()。   建议使用C ++ 11的random number generation工具   替换rand()

显然rand()有点过时,我将在答案结尾处解决。至于为什么在每次运行程序时都看到相同的值,这不是rand()的错误。 rand()是一个伪随机数生成器,可以生成貌似的随机数,但以完全确定的方式生成。为了在每次运行中获得不同的结果,您需要使用某种不可预测的东西(例如当前时间)来种子。这样做如下。

#include <cstdlib>
#include <ctime>
int main(){
    srand(time(0));
    // rand() will now behave differently on each run of the program
}

here也对此进行了说明。同样重要的是要注意,您应仅在程序开始时调用一次srand。如here所述,在同一秒内多次调用srand会得到相同的种子,从而产生来自rand的相同随机序列。


如果您想最正确,C ++ 11现在提供了一个不错的random number generation library,您应该考虑使用。用法示例如下:

#include <random>
std::random_device rd; // reliable random seed generator
std::default_random_engine randengine { rd() }; // global rng, seeded with random device

...

void Game::SelectHiddenWord(Fstring &word) {
    // NOTE: this vector can be static const if it never changes, to avoid
    // constructing and destructing it every function call
    static const std::vector<Fstring> WordList{ "plan","planet","planes","radios","gamers","images", "amigos","micros","macros","frogs","raids","roads","paris","smog","cars","macs","scam","some","farm","fair","jam","rat","map","zig","zag","isogram","amorist","roaming","mirages","soaring","cargos","disarm","isobar"};

    // define distribution as [ 0, WordList.size() )
    std::uniform_int_distribution<size_t> dist { 0, WordList.size() - 1 };
    word = WordList.at(dist(randengine));
}

我仍然对您提到的一件事感到困惑:

  

但是我希望rand函数始终生成数字14 [...]

如果这确实是您想要的,您可以将每个rand()替换为14:-)