为什么在 main 之前的函数中使用 rand/srand 时得到相同的数字?

Why do I get the same number when using rand/srand in a function before main?

为什么每次我 运行 我在 main 中的代码时得到一个不同的随机数,但是当我 运行 它在一个函数中时我得到一个静态数字?

(1) Main中的随机数...

int main()
{
    srand(time(0));
    int loot = 1+(rand()%9);
    cout << loot;
    return 0;
}

(2) main 之外的函数中的随机数...

using namespace std;

void lootTable(){
    srand(time(0));
    int loot = 1+(rand()%9);
    cout << loot;
}

int main()
{

    cout << lootTable;
    return 0;
}

解决了我的问题,已移除

cout << loot;

来自函数。

using namespace std;

int lootTable(){
    int loot = 1+(rand()%9);
}

int main()
{
    srand(time(0));
    cout << lootTable();
    return 0;
}

马上,您应该知道 std::cout << lootTable; 行在原始代码中的作用。它等效于 std::cout << <address of lootTable function>;,这是一个非零值,它被转换为布尔值,然后导致打印 1。编译时,建议highly开启警告,至少-Wall -Wextra。您会立即收到有关此问题的警告。

要调用函数,您必须始终使用参数列表,(),即使它是空的。

srand() 只应在程序中调用 一次 。它为您的 PRNG(伪随机数生成器)播种,而我们只为 PRNG 播种一次。最简单的方法是在 main().

开头
#include <cstdlib>
#include <ctime>
#include <iostream>

int lootTable() { return 1 + std::rand() % 9; }

int main() {
  std::srand(std::time(0));
  for (int i = 0; i < 10; ++i) {
    std::cout << lootTable() << ' ';
  }
  std::cout << '\n';
}

两次独立运行的输出:

~/tmp 
❯ ./a.out 
5 5 3 8 1 2 1 9 8 8 

~/tmp 
❯ ./a.out 
6 5 5 7 8 7 5 6 8 4

让我们看看looTable()。我使用了您尝试回答您自己的问题时的签名。一块块来看吧。

int lootTable()

这个非常简单。第一部分 int 表示函数 return 是一个整数。所以你的函数必须至少有一个 return 语句。您的初始版本有一个 void return 类型,这意味着该函数不会 return 一个值。这可能不适合您的预期用途。

然后,在您尝试的回答中,您得到了 return 类型的修复,但实际上 return 什么都没有,因此投反对票。

第二部分是名字,你好像记下来了,调用函数没有问题。

第三部分是参数列表,在你的例子中是空的。同样,这里似乎没有问题。


您应该使用 <random> 而不是使用 srand()/rand()。它的随机性不太确定,它将 PRNG 与您想要的分布类型分开​​。如果你有不同类别的战利品,下面的代码使用 std::uniform_int_distribution, which means every value has an equal chance of appearing. For a loot table, you might prefer a std::normal_distribution or std::lognormal_distribution or whatever 漂浮你的船。

下面是一个简短的示例程序:

#include <iostream>
#include <random>

int lootTable() {
  static std::mt19937 prng(std::random_device{}());
  static std::uniform_int_distribution<int> values(1, 9);

  return values(prng);
}

int main() {
  for (int i = 0; i < 10; ++i) {
    std::cout << lootTable() << ' ';
  }
  std::cout << '\n';
}

两次独立运行的输出:

~/tmp 
❯ ./a.out 
2 6 7 8 2 1 8 7 8 5 

~/tmp 
❯ ./a.out 
9 5 7 8 4 5 8 8 1 7

static 关键字允许 PRNG 和分布对象在函数调用之间持续存在。换句话说,它们不会在每次调用函数时都重新创建。这允许它们在您的程序期间表现最佳。

轻微切线:
使用单个 32 位值播种 std::mt19937 不太理想,但足以满足小程序的需要。正确的播种需要足够的额外工作,用 class 包裹 std::mt19937 以确保完全播种是理想的。但考虑到显示 <random> 已经离题太远的争论,我不会演示任何代码。但如果你好奇的话,这里有一个 link:https://kristerw.blogspot.com/2017/05/seeding-stdmt19937-random-number-engine.html