由于maclaurin系列扩展正弦,控制台崩溃导致纳输出

时间:2018-06-04 20:38:37

标签: c++ math sine

这是我的代码:

#include <iostream>
#include <cmath>

using namespace std;

int factorial(int);

int main()
{
    for(int k = 0; k < 100000; k++)
    {
        static double sum = 0.0;
        double term;
        term = (double)pow(-1.0, k) * (double)pow(4.0, 2*k+1) / factorial(2*k+1);
        sum = sum + term;
        cout << sum << '\n';
    }
}





int factorial(int n)
{
    if(n == 0)
    {
        return 1;
    }
    return n*factorial(n-1);
}

我只是想使用sine(4)的{​​{1}}扩展形式来计算maclaurin的值。对于每个控制台输出,值为“sine”。控制台发出错误并在10秒钟后关闭。我在IDE中没有任何错误。

2 个答案:

答案 0 :(得分:1)

您的方法存在多个问题。

您的阶乘函数无法返回int。返回值太大了,非常快。

使用pow(-1, value)获得交替的正/负效率是非常低效的,并且会很快产生不正确的值。您应该选择1.0或-1.0,具体取决于k的奇偶校验。

当您总结一系列长期术语时,您希望首先对具有最小幅度的术语求和。否则,由于现有的比特限制了您可以达到的范围,您将失去精确度。在您的情况下,四的幂由阶乘控制,因此您首先将最高量值相加。从另一端开始,你可能会获得更好的精确度。

在算法上,如果你要将4增加到2k + 1的幂然后除以(2k + 1)!,你应该保留两个因子列表(4,4,4,4 ...)和(2,3,4,5,6,7,8,9,......)并简化双方。同时有很多四肢要去除分子和分母。

即使有这四个,我也不确定你能在没有专门代码的情况下接近你设定的100000目标。

答案 1 :(得分:0)

正如其他人已经说过的那样,对于大k,你得到的中间结果的幅度太大而不适合双倍。来自k上的某个pow以及factorial将返回无限。这就是非常大的双打所发生的事情。然后,当你将一个无穷大除以另一个无穷大时,你得到了NaN。

处理过大数字的一个常见技巧是使用对数来表示中间结果,并且最后只应用指数函数一次。 这里需要一些对数的数学知识。要了解我在这里所做的事情,您需要了解exp(log(x)) == xlog(a^b) == b*log(a)log(a/b) == log(a) - log(b)

在您的情况下,您可以重写

pow(4, 2*k+1) 

exp((2*k+1)*log(4))

然后还有阶乘。 factorial(n) == gamma(n+1)功能可以帮助log(factorial(n)) == lgamma(n+1)pow(4, 2*k+1) / factorial(2*k+1) 。简而言之,lgamma为您提供了一个没有巨大中间结果的阶乘对数。

总结一下,替换

exp((2*k+1)*log(4) - lgamma(2*k+2))

使用

lgamma

这可以帮助您使用NaN。此外,这应该会提高效果,因为O(1)factorial中运行,而O(k)位于{{1}}。

但请注意,我仍然对您的结果在数值上准确无误。 双精度仍然限制在大约16位十进制数字的精度。你的100000次迭代很可能毫无价值,甚至可能有害。