首页 > 解决方案 > C++ 指数分布偶尔会返回预期为 0 的 inf

问题描述

在一个项目中,我正在生成数百万个 expo(lambda) 随机变量,其中 lambda 可能非常大。使用时,std::exponential_distribution<float>我偶尔会得到一个返回值inf。如果 lambda 接近 0,我会理解这一点,但是当 lambda 很大时,预期值非常接近于零。例如,以下程序通常在几百万次抽奖后终止:

#include<iostream>
#include<random>

int main(void)
{
    std::random_device rd;
    std::mt19937 generator(rd());

    float lambda = 1000000.0;
    float val = 0;

    for(int i = 0; i < 1000000000; ++i)
    {
        std::exponential_distribution<float> dist(lambda);
        val = dist(generator);

        if(isinf(val))
        {
            std::cout << i << " " << val << " failure" << std::endl;
            exit(0);
        }
    }

    return 0;
}

如果函数中有一些错误(由于精度),为什么它返回inf而不是更方便0.0?除了手动检查输出是否有限之外,还有什么方法可以解决这个问题?谢谢。

标签: c++random

解决方案


理查德克里顿的评论说:

“......如果 RealType 是浮点数,某些实现可能偶尔会返回无穷大。这是 LWG 问题 2524......”来源(有问题的链接):https ://en.cppreference.com/w/cpp/numeric/随机/指数分布

切换到double并不能解决这个问题,相反,它只会减少看到它的机会(或至少使它可以忽略不计)。正如 LWG 问题所指出的,根本问题是generate_canonical(某些实现可以利用)在极少数情况下可能会返回 1.0,因此-log(1-generate_canonical())可能会输出无穷大。在实践中,这float比 with更有可能,因为与 with 相比,可以产生double的数字要少得多(实际上是 2^24 而不是 2^53)。(无论如何,右尾分布的幼稚实现还有其他问题,例如指数分布;请参阅“重新调节分位数函数”。)generate_canonicalfloatdouble


推荐阅读