【问题标题】:Using a header file to define mt19937 and normal_distribution使用头文件定义 mt19937 和 normal_distribution
【发布时间】:2018-08-02 03:59:37
【问题描述】:

我正在使用以下例程来生成从高斯/正态分布中选择的随机数:

当所有内容都在一个文件中进行编译时,它相当简单:

#include <iostream>
#include <math.h>
#include <random>

using namespace std;

int main()
{
    double m;
    double v;
  int seed=100; 
    int samplesize=10;
    double ls [samplesize]; //to store as a list

    m = 0.0;
    v = 0.05;
    mt19937 e2(seed);

    normal_distribution<float> dist(m, sqrt(v));

  for (int i=0; i<samplesize; i++){
        ls[i] = dist(e2);
        cout << ls[i] << endl;
    }

    return 0;
}

现在我正在尝试做类似的事情,但我希望能够在全局范围内定义 e2dist,或者只是首先在听众文件中 .h 然后在各种 .C 中调用它们我的程序的文件。 我的尝试不断遇到error: invalid use of non-static member function ‘std::mt19937 e2(int)’ 类型的错误。

目标是:

  • 在头文件中定义e2dist
  • .C 文件中为e2 播种,该文件加载一个参数文件,其中包含给定种子的位置。
  • 在我的.C 文件中使用dist(e2) 来生成这样的数字。

我的尝试:

在我写的头文件中:

#include <random>

std::mt19937 e2(int sd); //sd for seed to be read from file later.
std::normal_distribution<float> dist(double meanNormal, double varNormal); //define generally, mean and var to be read from file.

然后在我读取参数的setup.C 文件中,我尝试生成e2dist 的实例:

e2(seed); //seed read from file before.
dist(mean,sqrt(var)); //mean and var are double variables defined in this file. 

现在在我的主程序文件中,当我尝试使用dist(e2)dist 生成一个数字时,我得到一个非静态成员函数错误,如上所示。 对于如何实现这一目标的任何帮助将不胜感激。

【问题讨论】:

    标签: c++ random header-files gaussian normal-distribution


    【解决方案1】:

    这是因为在第一个示例中您声明了变量e2dist,而在第二个示例中您定义了函数。

    你想要的是这个标题:

    #include <random>
    
    std::mt19937 e2;
    std::normal_distribution<float> dist;
    

    在您的主文件或.C 文件中,您应该:

    e2 = std::mt19937(seed);
    dist = normal_distribution<float>(m, sqrt(v));
    

    您还应该包含一个标头保护以防止多个声明。我假设您已经有一个,但为简洁起见没有包括它。

    【讨论】:

    • 这很好地解决了它!
    【解决方案2】:

    您创建了带有 2 个函数声明的标题

    std::mt19937 e2(int sd);
    std::normal_distribution<float> dist(double meanNormal, double varNormal);
    

    函数f2接受一个参数并返回std::mt19937对象,函数dist接受两个参数并返回std::normal_distribution对象。 在您的主文件中,您通过

    调用了这些函数
    e2(seed); //seed read from file before.
    dist(mean,sqrt(var)); //mean and var are double variables defined in this file.
    

    你在这一行遇到编译器错误

    ls[i] = dist(e2); // <----
    

    因为你想以e2函数作为参数调用dist函数,所以这是不可能的。 dist 函数需要两个双参数。

    如果您想将diste2 视为全局变量以在多个源文件中生成随机值,您可以像这样在头函数中声明

    double myrandom ();
    

    并将其定义为

    double myrandom ()
    {
      static mt19937 e2(100);
      static normal_distribution<float> dist(0.0, sqrt(0.05));
      // e2 and dist will be created during first call of this function
      return dist(e2);
    }
    

    【讨论】:

    • 在我提供的单个文件示例中,没有错误。仅当我尝试使用头文件和多个 .C 文件拆分内容时才会出现该错误。
    • 将代码拆分为头文件和主文件后,ls[i] = dist(e2); 这一行出现错误,因为在头文件中您将 e2 和 dist 声明为函数。我同意 ls[i] = dist(e2) 在一个主文件中有效。
    • 哦,我明白了。所以我不应该在头文件中完全定义它吗?我的意思是我可以在主文件本身中执行类似于您的double myrandom 的操作?
    【解决方案3】:

    你不能这样做。 std::mt19937 e2(int sd);

    不太确定为什么你认为这会起作用......正如指出的那样,这声明了一个函数。

    你能做的就是放

    std::mt19937 e2;
    

    在您的头文件中,然后从您的 .cpp 文件调用

    e2.seed(something);
    

    不过,这似乎是创建一个小类为您封装它的好机会。

    class RNG_class {
    private:
        std::mt19937 e2;
        std::normal_distribution<float> dist;
    public:
        RNG_class(int seed, double meanNormal, double varNormal) : e2(seed), dist(meanNormal, varNormal) {}
        float get() {
            return dist(e2);
        }
    };
    

    然后你可以从你的.cpp

    RNG_class rng(100, m, sqrt(v));
    ...
    ls[i] = rng.get();
    

    【讨论】:

      猜你喜欢
      • 2015-02-06
      • 1970-01-01
      • 1970-01-01
      • 2020-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      相关资源
      最近更新 更多