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

In c++ the rand() is generating different result when executing the program with and without debugging

本文关键字:调试 程序 c++ 结果 执行 rand      更新时间:2023-10-16

所以我一直在用 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((函数不是用于生成随机数的最佳方法。所以我在调试模式下启动了程序,我发现我现在的随机数整数是 32,这将使我从单词列表中获得"解除武装"一词。每次我使用调试模式时都会发生这种情况。

因此,在没有调试的启动时,我总是得到"烟雾"这个词,而在调试启动时,我总是得到"撤防"这个词,所以我真的可以玩两个词。

那么这是 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++编译器。

解决rand()在调试模式下的行为不同的原因是编译器供应商的问题。它在内部的工作方式是实现定义的(即由编译器的创建者决定(。从 cpp 首选项:

无法保证随机序列的质量 产生。[...] 不建议将rand()用于严重的随机数生成需求。 建议使用 C++11 的随机数生成工具 以替换rand().

显然rand()有点过时,我将在回答的最后解决。至于为什么您在每次运行程序时都会看到相同的值,这不是rand()的错误。rand()是一个伪随机数生成器,可以生成看似随机的数字,但以完全确定的方式。为了在每次运行时获得不同的结果,您需要在随机数生成器中植入一些不可预测的东西,例如当前时间。此操作如下。

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

这里也对此进行了解释。同样重要的是要注意,您应该只在程序开始时调用srand一次。在同一秒内多次调用srand将导致相同的种子,从而从rand中产生相同的随机序列,如此处所述。


如果你想最正确,C++11 现在提供了一个很好的随机数生成库,你应该考虑使用。示例用法可能如下所示:

#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 [...]

如果这真的是您想要的,您可以用14替换每个rand():-(