指数生成器c++,有时返回inf

exponential number generator c++, sometimes returns inf

本文关键字:返回 inf c++ 指数      更新时间:2023-10-16

我正在进行模拟,我使用了一个函数来生成模拟指数分布的数字(我不想使用c++11函数)

这是代码

long double exponential(long double l)
{
long double mean = l;
long double u = ((long double)rand() / ((long double)RAND_MAX + 1.0));
return (-log(u) * mean);
}

有时返回的值是inf,你知道为什么吗,可能是0以某种方式出现了吗?

这是一个合乎逻辑的好结果。每个函数log(arg):

如果arg为​0​.在这种情况下返回CCD_ 3。

对于rand()返回的零值,您有范围错误inf(无限)值。

根据定义,如果(分子(long double)rand()为0),u可能为零

已编辑

尝试:

long double exponential(long double l)
{
int NUM_TRIES = 1000; // How many times to mine a non zero u before giving up?
long double mean = l;
long double DEF  = 1; // Put your default value here
long double u;
do { 
    u = ((long double)rand() / ((long double)RAND_MAX + 1.0));
}while(u == 0 && NUM_TRIES--);
if(NUM_TRIES == 0) { 
    return DEF;
} else if(u != 0) { 
  return (-log(u) * mean);
}

不要使用rand

rand函数在这种情况和许多其他情况下被认为是邪恶的。既然你很幸运能使用C++,为什么不利用<random>标头的美丽新功能呢?

你只需要使用std::uniform_real_distribution就可以了:

std::random_device rnd_dev;
std::mt19937 gen(rnd_dev());
long double precision = 0.000001;
std::uniform_real_distribution<long double> dis(precision, 1.0 - precision);
std::cout << dis(gen) << 'n'; 

这是一个活生生的例子。


如果您仍然想使用rand

问题显然在于rand返回0,并且导致u也是0。在这种情况下,log将按照您的问题中所述返回-inf

解决方案是查看您允许的最接近0的数字:

long double u = rand() / (RAND_MAX + 1.0);

(重写的代码,因为结果总是一个浮点数),即:

long double precision = 1 / (RAND_MAX + 1.0);

从中可以很容易地看出,我们想要生成的数字在precision1.0 - precision之间,这很容易通过实现

long double precision = 1 / (RAND_MAX + 1.0);
long double random = rand();
if (random == 0) random = precision;
long double u = random / (RAND_MAX + 1.0);

固定具有CCD_ 22的情况。

当然,随机分布不再是均匀的,因为u成为precision的概率几乎是任何其他数字的概率的两倍。但这是你以前遇到的问题(见第一个链接)。