【问题标题】:Getting "-nan(ind)" when trying to generate random variates尝试生成随机变量时获取“-nan(ind)”
【发布时间】:2023-03-18 16:35:01
【问题描述】:

我正在尝试通过使用极坐标以及平均值和西格玛值来生成两个标准正态变量 r1、r2 来生成随机变量。然而,当我运行我的代码时,我不断得到一个“-nan(ind)”作为我的输出。

我在这里做错了什么?代码如下:

static double saveNormal;
static int NumNormals = 0;
static double PI = 3.1415927;

double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

static double normal(double r, double mean, double sigma) {
    double returnNormal;
    if (NumNormals == 0) {
        //to get next double value
        double r1 = fRand(0, 20);
        double r2 = fRand(0, 20);
        returnNormal = sqrt(-2 * log(r1)) * cos(2 * PI*r2);
        saveNormal = sqrt(-2 * log(r1)) * sin(2 * PI*r2);
    }
    else {
        NumNormals = 0;
        returnNormal = saveNormal;
    }
    return returnNormal*sigma + mean;
}

【问题讨论】:

    标签: c++ random


    【解决方案1】:

    因此,您正在使用 Box–Muller 方法对正态随机变量进行伪随机抽样。为了使这个变换起作用,r1r2 必须是 [0,1] 中均匀分布的独立变量。

    相反,您的 r1/r2 支持 [0,20],当 >1 时会产生负的 sqrt 参数,这将为您提供 nans。替换为

    double r1 = fRand(0, 1);
    double r2 = fRand(0, 1);
    

    此外,您应该使用 C++11 <random> 来更好地生成伪随机数;截至目前,由于rand()-to-double 转换以及相邻呼叫之间可能存在虚假相关性,您的fRand 质量很差。此外,您的函数缺少一些基本的错误检查,并且严重依赖全局变量,并且本质上是线程不安全的。

    仅供参考,这就是 C++11 版本的样子

    #include <random>
    #include <iostream>
    
    int main()
    {
      auto engine = std::default_random_engine{ std::random_device{}() };
      auto variate = std::normal_distribution<>{ /*mean*/0., /*stddev*/ 1. };
    
      while(true) // a lot of normal samples ...
        std::cout << variate(engine) << std::endl;
    }
    

    【讨论】:

    • “由于 rand()-to-double 转换,您的 fRand 质量很差”——确实,每个人都需要停止使用 rand(),忘记它曾经存在过。 :-) 请参阅 Stephan T. Lavavej 在 GoingNative 2013 上的精彩演讲:rand() Considered Harmful
    【解决方案2】:

    r1 可以为零,使log(r1) 未定义。


    此外,请勿使用rand(),除非您需要让您的数字在匆忙中看起来很随机。 Use &lt;random&gt; instead

    【讨论】:

    • 关于零奇点的好点!但是,如果 r1 > 1,log(r1) 仅大于零。 (很可能在发布的代码中。)也许你打错了?
    • @ArneVogel:哦,你说得对,我删除了那部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-12
    • 1970-01-01
    • 2011-06-26
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多