C++ 中的种子随机数生成器
C++ 等编程语言不会生成真正的随机数。相反,计算机使用数学函数生成伪随机数。
本文讨论了生成随机数中种子的概念以及为 C++ 中用于生成随机数的函数提供种子的方法。
C++ 中随机数生成器中种子的概念
C++ 使用确定性算法生成随机数序列。因此,数字序列是伪随机的,而不是纯粹的概率。
在这种情况下,种子充当算法的起点。你不应将其视为生成的第一个数字将是种子。
相反,该算法从种子定义的分布中随机选择数字。如果你为算法提供相同的种子,它将生成相同的伪随机数序列。
但是,大多数情况下,你可能需要为每次执行生成不同的伪随机数序列。在这种情况下,你需要在每次执行算法时为其提供不同的种子。
使用 srand()
函数在 C++ 中播种随机数生成器
srand()
函数接受无符号整数作为参数。它使用参数为生成伪随机数的算法播种。
语法:
void srand (unsigned int seed);
如果你提供 1
作为 srand()
函数的参数,它会将伪随机数生成器初始化为其初始值。生成器产生与上次调用 rand()
函数相同的结果。
让我们看一个示例,该示例使用从用户那里获取的任意数字作为输入来播种伪随机数生成器。
示例代码:
#include<iostream>
using namespace std;
int main()
{
unsigned int seed;
cout<<"Enter seed value:\n";
cin>>seed;
srand(seed);
cout<<"Successfully seeded the generator\n";
return 0;
}
输出:
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ g++ seed_example.cc
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ ./a.out
Enter seed value:
12
Successfully seeded the generator
使用 time()
函数在 C++ 中播种随机数生成器
前一种方法的问题是用户可以多次输入相同的数字。如果你需要确保每次执行算法时都提供不同的种子,请使用 time()
函数为伪随机数生成器提供种子。
C++ 中的 time()
函数返回当前 UNIX 时间戳,即自 UTC 时间 1970 年 1 月 1 日 00:00 小时以来经过的秒数。
语法:
time_t time (time_t* timer);
该函数将参数作为 time_t
类型的指针。如果你提供对函数的非空引用作为参数,它会将 time_t
类型的对象设置为保存当前时间戳的参数。
time_t
类型是算术类型的别名,可以保存当前的 UNIX 时间戳值。它实际上是一个无符号整数值。
示例代码:
#include<iostream>
using namespace std;
int main()
{
srand(time(NULL));
cout<<"Successfully seeded the generator\n";
return 0;
}
请注意,代码将 NULL
作为参数传递给 time()
函数。根据代码,出于任何原因,你不需要类型为 time_t
的对象。
输出:
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ g++ seed_example.cc
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ ./a.out
Successfully seeded the generator
播种要避免的随机生成器错误
通常,你在代码的循环中生成一系列伪随机数。大多数人犯的一个常见错误是每次循环执行时都为生成器播种。
在这种情况下,你可能会得到重复的数字,因为每次你使用相同的数字播种时,生成器都会创建相同的数字序列。
即使你使用 time()
函数为随机生成器播种也是如此,因为 time()
函数返回自过去某个固定日期以来经过的秒数。
另一方面,循环将执行得更快,因此每次调用 time()
函数将保持返回相同的值,直到经过一秒。这样,你最终将向生成器播种相同的值。
示例代码:
#include<iostream>
using namespace std;
int main()
{
for(int i=1;i<=10;i++)
{
srand(time(NULL));
cout<<rand()<<" ";
}
cout<<endl;
return 0;
}
输出:
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ g++ seed_example.cc
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ ./a.out
1524491454 1524491454 1524491454 1524491454 1524491454 1524491454 1524491454 1524491454 1524491454 1524491454
代码在循环内播种随机生成器,并且执行十次相同的结果。你应该始终在循环之前为随机数生成器播种以避免这种陷阱。
让我们看一下代码在循环外播种随机生成器的示例。
示例代码:
#include<iostream>
using namespace std;
int main()
{
srand(time(NULL));
for(int i=1;i<=10;i++)
{
cout<<rand()<<" ";
}
cout<<endl;
return 0;
}
输出:
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ g++ seed_example.cc
mohtashim@mohtashim:~/eclipse-workspace/Java2Blog$ ./a.out
213462937 1076978976 1207347426 8310730 1551061902 266528745 944000672 871831053 1678325834 868781842
观察代码导致不同的数字序列。
结论
你可以将种子提供给充当算法起点的伪随机生成器,但你应该小心避免陷阱,如文章中所述。否则,可能会导致不需要的结果。
相关文章
在 C++ 中通过掷骰子生成随机值
发布时间:2023/04/09 浏览次数:169 分类:C++
-
本文解释了如何使用时间因子方法和模拟 C++ 中的掷骰子的任意数方法生成随机数。了解它是如何工作的以及它包含哪些缺点。提供了一个 C++ 程序来演示伪数生成器。
在 C++ 中使用模板的链表
发布时间:2023/04/09 浏览次数:158 分类:C++
-
本文解释了使用模板在 C++ 中创建链表所涉及的各个步骤。工作程序演示了一个链表,该链表使用模板来避免在创建新变量时声明数据类型的需要。
在 C++ 中添加定时延迟
发布时间:2023/04/09 浏览次数:142 分类:C++
-
本教程将为你提供有关在 C++ 程序中添加定时延迟的简要指南。这可以使用 C++ 库为我们提供的一些函数以多种方式完成。
在 C++ 中创建查找表
发布时间:2023/04/09 浏览次数:155 分类:C++
-
本文重点介绍如何创建查找表及其在不同场景中的用途。提供了三个代码示例以使理解更容易,并附有代码片段以详细了解代码。
如何在 C++ 中把字符串转换为小写
发布时间:2023/04/09 浏览次数:63 分类:C++
-
介绍了如何将 C++ std::string 转换为小写的方法。当我们在考虑 C++ 中的字符串转换方法时,首先要问自己的是我的输入字符串有什么样的编码
如何在 C++ 中确定一个字符串是否是数字
发布时间:2023/04/09 浏览次数:163 分类:C++
-
本文介绍了如何检查给定的 C++ 字符串是否是数字。在我们深入研究之前,需要注意的是,以下方法只与单字节字符串和十进制整数兼容。
如何在 c++ 中查找字符串中的子字符串
发布时间:2023/04/09 浏览次数:65 分类:C++
-
本文介绍了在 C++ 中检查一个字符串是否包含子字符串的多种方法。使用 find 方法在 C++ 中查找字符串中的子字符串
如何在 C++ 中把字符串转换为 Char 数组
发布时间:2023/04/09 浏览次数:107 分类:C++
-
本文介绍了在 C++ 中把字符串转换为 char 数组的多种方法。使用 std::basic_string::c_str 方法将字符串转换为 char 数组
如何在 C++ 中把 Char 数组转换为字符串
发布时间:2023/04/09 浏览次数:201 分类:C++
-
本文介绍了在 C++ 中将 char 数组转换为字符串的多种方法。使用 std::string 构造函数将 char 数组转换为 string