用系列近似log(2)

时间:2016-10-05 03:11:21

标签: c++ algorithm

double k = 0; 
int l = 1;
double digits = pow(0.1, 5);

do 
{
    k += (pow(-1, l - 1)/l);
    l++;
} while((log(2)-k)>=digits);

我正在尝试根据我看到的使用一系列Σ_(l = 1)(pow(-1,l - 1)/ l)来估算log(2)的例子来编写一个小程序;

它应该是一个猜测细化的东西,它越来越接近正确的值,直到这么多的数字匹配。

以上就是我尝试的但是它没有出来。在弄乱了很长一段时间后,我无法弄清楚我在哪里弄乱。

1 个答案:

答案 0 :(得分:1)

我假设你试图通过泰勒系列扩展来扩展2的自然对数:

         ∞ (-1)n + 1
 ln(x) =  ――――――――(x - 1)n
         n=1   n 

您的代码的一个问题是选择以指定的精度停止迭代的条件:

do { ... } while((log(2)-k)>=digits);

除了直接使用log(2)之外(你不应该找到它而不是使用库函数吗?),在第二次迭代(以及其他每次迭代)log(2) - k得到负(-0.3068 ......)结束循环。

可能(但不是最佳)修复可能是使用std::abs(log(2) - k),或者当1.0 / l的绝对值(这是两次连续迭代之间的差异)足够小时结束循环。

此外,使用pow(-1, l - 1)来计算序列1,-1,1,-1,......实际上是一种浪费,特别是在收敛速度较慢的系列中。

更有效的系列(见here)是:

           ∞     1 
 ln(x) = 2   ――――――― ((x - 1) / (x + 1))2n + 1
           n=0 2n + 1  

您可以在不使用pow的情况下进行评估:

double x = 2.0;  // I want to calculate ln(2)

int n = 1;
double eps = 0.00001,
       kpow = (x - 1.0) / (x + 1.0),
       kpow2 = kpow * kpow,
       dk,
       k = 2 * kpow;

do {
    n += 2;
    kpow *= kpow2;
    dk = 2 * kpow / n;
    k += dk;
} while ( std::abs(dk) >= eps );