0

我搜索了计算数字 x 的 ln 的方程,发现这个方程是:

在此处输入图像描述

我写了这段代码来实现它:

double ln = x-1 ;
    for(int i=2;i<=5;i++)
    {
        double tmp = 1 ;
        for(int j=1;j<=i;j++)
            tmp *= (x-1) ;
        if(i%2==0)
            ln -= (tmp/i) ;
        else
            ln += (tmp/i) ;
    }
    cout << "ln: " << setprecision(10) << ln << endl ;

但不幸的是,我得到的输出与我的计算器上的输出完全不同,尤其是对于大数字,谁能告诉我问题出在哪里?

4

6 回答 6

1

您链接到的方程式是一个无限级数,正如方程式主要部分后面的省略号所暗示的那样,并且在同一页面上的前面的公式中更明确地表明了这一点:

在此处输入图像描述

在您的情况下,您只计算前四个术语。后面的术语将对结果进行小的改进以更接近实际值,但最终计算所有无限步将需要无限时间。

但是,您可以做的是近似您对以下内容的响应:

double ln(double x) {
  // validate 0 < x < 2
  double threshold = 1e-5;  // set this to whatever threshold you want
  double base = x-1;        // Base of the numerator; exponent will be explicit
  int den = 1;              // Denominator of the nth term
  int sign = 1;             // Used to swap the sign of each term
  double term = base;       // First term
  double prev = 0;          // Previous sum
  double result = term;     // Kick it off

  while (fabs(prev - result) > threshold) {
      den++;
      sign *=- 1;
      term *= base;
      prev = result;
      result += sign * term / den;
  }

  return result;
}

注意:我还没有实际测试过这个,所以它可能需要一些调整。

这样做是计算每个术语,直到两个连续术语之间的绝对差小于您建立的某个阈值。

现在这不是一种特别有效的方法。最好使用您正在使用的语言(在本例中为 C++)提供的函数来计算自然对数(我相信另一张海报已经向您展示过)。但是自己尝试一下,看看它是如何工作的,可能会有一些价值。

x此外,正如下面的 barak manos 所指出的,这个泰勒级数只收敛于 (0, 2) 范围内,因此在尝试运行实际计算之前,您需要验证该范围内的谎言值。

于 2014-11-08T19:31:36.320 回答
0

我相信 C++ 语言中的自然 log 就是 log

于 2014-11-08T19:04:13.547 回答
0

该公式不适用于大量输入,因为它需要您考虑最高学位的成员,而您不能因为它们是无穷多的。它仅适用于少量输入,其中只有您的系列的第一个术语是相关的。

你可以在这里找到方法:http://en.wikipedia.or/wiki/Pollard%27s_rho_algorithm_for_logarithms

在这里: http: //www.netlib.org/cephes/qlibdoc.html#qlog

于 2014-11-08T19:07:42.110 回答
0

long使用andlong double代替intand不会有什么坏处double。这可能会在一些较大的值上获得更高的准确性。此外,您的系列仅延伸 5 级深度也限制了您的准确性。

使用这样的系列基本上是对数答案的近似值。

于 2014-11-08T19:26:01.813 回答
0

这个版本应该更快一些:

double const scale = 1.5390959186233239e-16;
double const offset = -709.05401552996614;

double fast_ln(double x)
{
    uint64_t xbits;
    memcpy(&xbits, &x, 8);
    // if memcpy not allowed, use 
    //       for( i = 0; i < 8; ++i ) i[(char*)xbits] = i[(char*)x];
    return xbits * scale + offset;
}

诀窍在于,这使用了 64 位整数 * 64 位浮点乘法,其中涉及整数到浮点的转换。所述浮点表示类似于科学记数法,需要对数来找到合适的指数……但它完全是在硬件中完成的,而且速度非常快。

然而,它在每个八度音程内进行线性近似,这不是很准确。对这些位使用查找表会好得多。

于 2014-11-08T20:21:03.253 回答
0

这应该有效。您只需要 if x>=2 将 x 缩小一半并添加 0.6931 的部分。0.6931 的原因是 ln(2)。如果您愿意,可以添加 if (x >= 1024) return myLN(x/1024) + 6.9315,其中 6.9315 是 ln(1024)。这将为 x 的大值增加速度。具有 100 的 for 循环可能远不像 20。我相信可以获得整数 17 的准确结果。

double myLN(double x) {

    if (x >= 2) {
        return myLN(x/2.0) + 0.6931;
    }

    x = x-1;

    double total = 0.0;
    double xToTheIPower = x;

    for (unsigned i = 1; i < 100; i++) {

        if (i%2 == 1) {
            total += xToTheIPower / (i);
        } else {
            total -= xToTheIPower / (i);
        }

        xToTheIPower *= x;
    }

    return total;
}
于 2019-02-26T02:17:34.390 回答