【问题标题】:Semi-Random Number Generation C++半随机数生成 C++
【发布时间】:2019-03-30 13:58:09
【问题描述】:

我正在运行蒙特卡洛模拟,生成 100,000 条随机路径。我的问题是我想找到一种方法将这些相同的 100,000 条随机路径保留在其他变量的循环中。本质上,我希望我的随机数生成器在每次运行 100,000 次迭代时重置。目前,我的代码看起来像这样:

 vector<double>Rand_Var(double time)
 {
    static mt19937 generator;

    normal_distribution<>ND(0., 1.);
    ND(generator);
    double phi;
    vector<double> rand(time + 1);
    for (int i = 1; i <= time; i++)
    {
      phi = ND(generator);
      rand[i] = phi;        
    }

    return rand;
}

然后在main() 进行测试我有:

for (int l = 0; l < 5; l++)
{   
    for (int i = 0; i <= 1; i++)
    {   
        vector<double>rand_val = Rand_Var(time_opt);            
        cout << rand_val[4] << endl;
    }
}

我得到以下输出:

-0.214253
 1.25608
-1.82735
 0.919376
 1.45366
-0.791957
 0.530696
 0.0751259
-0.559636
-0.709074

然而,我想得到的是:

-0.214253
 1.25608
-0.214253
 1.25608
-0.214253
 1.25608
-0.214253
 1.25608
-0.214253
 1.25608

这可能吗?

【问题讨论】:

  • 您是否尝试过重新播种到相同的种子? (即:将当前时间存储在一个变量中,然后每次您想要重置时都使用该时间重复调用.seed()?)
  • 为什么每次使用 rand 列表时都要重建它。当我看到第一个函数时,我想,'好吧,他只生成一次随机数,昂贵但肯定能工作'。但你每次都重建
  • @scohe001 -- 将其作为答案。
  • @pm100 这看起来是个不错的答案。
  • 您是否希望Rand_Var 始终为传入的相同time 返回相同的向量?

标签: c++ loops random


【解决方案1】:

如果您想再次获得同一组随机数,只需 reseed your generator 到同一个种子!

例如:

vector<double>Rand_Var(double time, bool should_reset) {
    static time_t my_seed = time(0);
    static mt19937 generator(my_seed);
    if(should_reset) { generator.seed(my_seed); } //reseed and reset!

    ...

然后在你的循环中:

for (...){
    bool should_reset = true;

    for (...) {
        vector<double>rand_val = Rand_Var(time_opt, should_reset);
        should_reset = false;
        ...
    }
}

【讨论】:

  • 现在每次都给我相同的价值。我确信这与我的代码设置方式有关。不幸的是,我对正确播种我的代码知之甚少。
  • @KWood 你不希望每次调用函数时都使用相同的值集吗?
  • 不,这有点棘手。我想要一个重复的随机数组合。在我的内部循环中说我的第一组随机数是:6,10,2,1。然后我得到一组新的随机数 95,8,14,7。对于我的外部循环,我希望每次都能重新生成这些完全相同的“随机”数字。我正在创建 100,000 条应该是随机的需求路径,但我需要能够多次重新生成相同的 100,000 条路径。
  • @KWood 请编辑问题(并修改其示例)以明确这一点。您可能只需要在调用生成 100000 * 260 值的函数之前为生成器播种一次,然后将该种子用于任何后续计算。
  • @scohe001 看起来成功了!我非常感谢。我将运行一些测试和检查,但这应该可以节省大量时间,而不必手动运行我的不同参数。一个快速的问题,如果我有很多嵌套循环,其中 rand_val 部分位于最中心,那么 bool should_reset=true 是否应该在最外层循环中?
【解决方案2】:

如果您希望每 100,000 个随机数都相同,则将生成器包装在一个函数中并保留一个计数器。这会给你一个随机函数,比如

double random()
{
    static std::mt19937 generator;
    static int counter = 0;
    if (counter % 100000 == 0) // reset every 100000 times.
        generator.seed();
    normal_distribution<> dis(0., 1.);
    counter++;
    return dis(generator);
}

如果您希望每 100,000 次对 Rand_Var 的调用始终返回,那么您只需要做同样的事情

std::vector<double> Rand_Var(std::size_t time)
{
    static std::mt19937 generator;
    static int counter = 0;
    if (counter % 100000 == 0) // reset every 100000 times.
        generator.seed();
    normal_distribution<> dis(0., 1.);
    counter++;
    std::vector<double> data;
    data.reserve(time);
    std::generate_n(std::back_inserter(data), time, [&](){ return dis(generator); });       
    return data;
}

【讨论】:

    【解决方案3】:

    如果你使用一个静态变量,那么它会被初始化一次并一直生成新的数字。

    只要去掉静态,每次调用函数都会初始化并使用相同的种子。

    如果您需要多个数字(不清楚时间是什么,它是随机性的索引还是值?),请将 rng 作为参数传递:

    vector<double>Rand_Var(mt19937& rng, double time);
    

    并在您的第一个 for 循环中创建一个新的。

    for (int l = 0; l < 5; l++)
    {
        mt19937 generator;
        for (int i = 0; i <= 1; i++)
        {
            auto rand_val = Rand_Var(generator , time_opt);
    

    【讨论】:

    • 抱歉澄清。这个随机数生成器生成 260 个随机数,我用它们来模拟需求路径。然后我有这个需求路径的 100,000 次迭代。我希望 100,000 条需求路径中的每一条都不同,但每次重复该过程时都希望有相同的 100,000 条路径。
    • 所以只要把随机生成器的创建和种子集放在260*100000随机数生成的开头即可。就像这里一样,并将随机生成器传递给相关函数。为了更好的设计,它也可以被封装在一个类中。
    猜你喜欢
    • 1970-01-01
    • 2012-03-18
    • 2015-07-19
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多