为什么在 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
为什么每次我 运行 我在 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