如何编写随机数生成器函数



故事:使用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;
}

最新更新