故事:使用C++中的rand()
函数,我可以获得随机数,使用%
我可以设置范围。然而,如果我也想添加偏差,那么我也必须在结果中添加偏差。这是太多的工作要做,所以我决定编写自己的函数来处理这个问题。然而,我在某一点上陷入了困境
我知道,每次程序运行时,我都必须输入一个新的序列(srand(time(NULL))
(,否则我会一直得到相同的数字。
显而易见的方法是在main()
函数中插入srand(time(NULL))
。然而,我不想这样做,我希望在包含.h
文件时,它能自动完成。
假设myFunctions.h
:
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
int randint(int start, int end);
和myFunctions.cpp
:
#include "myFunctions.h"
/* [start,end) */
int randint(int start, int end)
{
return (rand() % (end - start)) + start;
}
现在,我不知道应该在哪里添加srand()
。如果我在randint()
定义中这样做,我假设,由于时间差太低,time(NULL)
将为循环的每一步评估相同的值,并且当我想在很短的时间内获得随机数时,它将一直提供相同的种子,比如:
for(int i = 0; i < 50; i++){
std::cout << randint(0, 3) << std::endl;
}
输出是相同的数字,50次。所以这证实了我的怀疑。
我在我的randint()
定义中尝试过这样的东西
int randint(int start, int end)
{
#ifndef SEED
srand(time(NULL));
#define SEED
#endif
return (rand() % (end - start)) + start;
}
然而,它也不起作用,因为我认为#ifndef
在预处理阶段只执行一次。
因此,在这些尝试之后,我试图在.h
文件的开头调用srand()
,但我遇到了这样一个事实,即实际上你不能调用任何函数之外的函数(例如main()
(
简言之,我现在陷入困境,任何帮助都将不胜感激。
如果我是你,我会实现一个类来封装所有函数。你可以称它为randomGen或类似的东西,然后在该类中包含你想要使用的所有函数。然后包括一个调用srand()
的构造函数。然后你可以在main中创建一个randomGen对象,然后你可以继续生成你的随机数。
使用C++11以后提供的call_once
函数。这需要使用<mutex>
。您必须创建一个once_flag
辅助对象。f
必须是静态的,这样它才能通过函数调用持久存在。本例使用lambda,但您也可以很容易地创建一个名为seedrand()
或其他的常规旧函数,并将其作为参数传入。
示例从https://en.cppreference.com/w/cpp/thread/call_once并根据您的程序进行了修改。
#include <iostream>
#include <mutex>
int randint(int start, int end)
{
static std::once_flag f;
std::call_once(f, []() {srand(time(NULL)); std::cout << "Random Seededn"; });
return (rand() % (end - start)) + start;
}
int main(int argc, char** argv)
{
for (int i = 0; i < 10; i++)
{
std::cout << i << ": " << randint(1, 100) << "n";
}
}
如果要将srand
作为函数直接传递,则必须将其参数作为附加参数传递。注意srand
之后缺少()
。您不希望将srand
的RESULT传递给call_once
,而是希望传递函数本身。call_once
会为您打电话。
static std::once_flag f;
std::call_once(f, srand, time(NULL)); // notice the lack of () after srand
编辑:std::call_once
过度杀伤
事实上,您需要使用pthread
来编译它,这太荒谬了。只有当您有多个线程调用同一段代码并且只希望它执行一次时,才应该使用std::call_once
来执行类似的操作。
更简单的解决方案是只使用静态布尔值:
int randint(int start, int end)
{
static bool seeded = false;
if (!seeded)
{
srand(time(NULL));
seeded = true;
}
return (rand() % (end - start)) + start;
}