#inf c ++ visual studio

时间:2016-04-22 01:07:51

标签: c++ visual-studio

我在计算双重总和时遇到了问题。当我将迭代设置为100000时,函数Asian_call_MC仍然返回一个数字。但是,当我将迭代设置为大约500000及以上时,它开始返回1.#INF。有人能告诉我它为什么会发生以及如何解决它?我正在使用visual studio 2013来编写c ++代码。

double Avg_Price(double init_p, double impl_vol, double drift, int step, double deltasqrt)
{
//Calculate the average price of one sample path
//delta  = T/ step
//drift = (risk_free - div_y - impl_vol*impl_vol / 2)*(T / step)
double Sa = 0.0;
double St = init_p;

for (int i = 0; i < step; i++)
{
    St = St*exp(drift + impl_vol*deltasqrt*normal_gen());
    //Sa = Sa * i / (i + 1) + St / (i + 1);
    Sa += St;
}
Sa = Sa / double(step);
return Sa;
}


double Asian_call_MC(double strike_p, double T, double init_p, double impl_vol, double risk_free, double div_y, int iter, int step)
{
//Calculate constants in advance to reduce computation time
double drift = (risk_free - div_y - impl_vol*impl_vol / 2)*double(T / step);
double deltasqrt = sqrt(double(T / step));


//Generate x1, average x and y
double cur_p = Avg_Price(init_p,impl_vol,drift,step,deltasqrt);
double pay_o=0.0;
double x = max(cur_p - strike_p,0.0);
//double y = pow(x, 2.0);


//Generate x2 to xn
for (int i = 0; i < iter; i++)
{
    cur_p = Avg_Price(init_p, impl_vol, drift, step, deltasqrt);
    x = max(cur_p - strike_p,0.0);
    //double q = double(i) / double(i + 1);
    //pay_o = pay_o *i/(i+1) + x / (i + 1);
    pay_o += x;
    //y = (1 - (1 / (i + 1)))*y + x*x / (i + 1);
}
//pay_o = pay_o / double(iter);
//stdev = sqrt((y - pow(pay_o , 2)) / (iter - 1));
//return pay_o*exp(-risk_free*T) ;
return pay_o;
}

3 个答案:

答案 0 :(得分:1)

当您增加迭代次数时,您将增加总和的值。在某些时候,该值会溢出double中可能包含的值,从而返回表示无穷大的1.#INF值作为您计算的值。这样做是因为计算出的值大于一对中的值。

要解决此问题,您需要将保存总和的变量更改为可以保存的数字大于double的变量。起点是使用long double

另一种选择是在for循环后构建一些逻辑,以便处理较小的数字。如何执行此操作将取决于您要精确计算的字符串。

答案 1 :(得分:0)

你已经满溢双重所能容纳的东西。 INF是无穷大的缩写,是溢出浮点时得到的错误代码。

根据编译器的不同,long double可能会有所帮助,也可能没有帮助。在Microsoft C ++中,我认为long double和double都是64位,所以没有运气。

查看Boost multiprecision库,它有更大的类型,如果你真的需要大的东西,不能重做你的数学。我看到你正在成倍增加然后分裂。你可以将一些乘法,然后除法,然后再乘以一些来节省空间吗?

答案 2 :(得分:0)

看起来你想要计算平均值。大多数人学习计算均值的方法是总结所有的值,然后将总和除以导致总和的值的数量。

这种方法存在一些与之相关的问题 - 例如,在一起添加多个值可能会给持有它的变量一个太大的总和。

经常使用另一种技术,它会积累一个&#34;运行&#34;意味着而不是总和。运行平均值的值始终是已累积的所有样本的平均值,因此它永远不会爆炸成溢出(浮点无穷大)值(除非其中一个累积样本为无穷大)。

下面的示例演示了如何计算运行平均值。它还计算总和,并显示总和/计数与运行平均值的比较(表明它们是相同的 - 我没有让它运行足够长的时间来溢出总和)。

该示例使用C-Library rand(),用于演示目的 - 我只需要一些东西来计算平均值。

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>

int main() {
        srand(static_cast<unsigned>(time(0)));

        double count = 0;
        double running_mean = 0;
        double sum = 0;

        auto start = time(0);
        auto end = start + 5;
        while(time(0) < end) {
            double sample = rand();
            count += 1;
            running_mean += (sample - running_mean)/count;
            sum += sample;
        }

        std::cout << std::setprecision(12);
        std::cout << "running mean:" << running_mean << "  count:" << count << '\n';
        double sum_mean = sum / count;
        std::cout << "sum:" << sum << "  sum/count:" << sum_mean << '\n';
}

编辑:他已经尝试过这个 - 该技术出现在我在OP代码

中遗漏的注释掉的行中

与通过累积总和来计算平均值不同,运行平均技术不能简单地在某个时刻溢出。因此,知道他已经尝试过并且它没有帮助解决这个问题,可能的原因就是迭代的一个术语本身就是INF。只要添加单个INF术语,累积的总和或平均值将变为INF并保持INF。

代码中最可能的部分是normal_gen(),用于调用exp函数。名称normal_gen()听起来像是正常分布的随机值的来源。通常的实现采用Box-Muller变换,其不能产生超过平均值约7个标准偏差的值。因此,如果Box-Muller生成器导致INF,则可能在比报告的迭代次数更少的情况下发生。但是,更先进的生成器可以产生更多的极值 - 理想情况下,正态分布具有非零概率产生任何有限实际值。

如果一个随机大的Normal样本是引起问题的原因,那么它与迭代计数增加的相关性就不会是更多的迭代使总和膨胀,通过添加更多的值来溢出 - 这将是更多迭代给出的该程序更有可能达到一个不太可能的随机值,这将导致一个INF术语。