【问题标题】:Trying to compute e^x when x_0 = 1当 x_0 = 1 时尝试计算 e^x
【发布时间】:2018-02-19 06:36:01
【问题描述】:

我正在尝试计算 x_0 = 1 处 e^x 的泰勒级数展开式。我很难理解我真正要寻找的是什么。我很确定我正在尝试找到当 x_0 = 1 时 e^x 时的十进制近似值。但是,当我在 x_0 = 0 时运行此代码时,我得到了错误的输出。这让我相信我计算不正确。

这是我的课程 e.hpp

#ifndef E_HPP
#define E_HPP

class E
{
    public:
        int factorial(int n);
        double computeE();

    private:
        int fact = 1;
        int x_0 = 1;
        int x = 1;
        int N = 10;
        double e = 2.718;
        double sum = 0.0;

};

这是我的 e.cpp

#include "e.hpp"
#include <cmath>
#include <iostream>

int E::factorial(int n)
{
    if(n == 0) return 1;
    for(int i = 1; i <= n; ++i)
    {
        fact = fact * i;
    }

    return fact;
}

double E::computeE()
{
    sum = std::pow(e,x_0);

    for(int i = 1; i < N; ++i)
    {
        sum += ((std::pow(x-x_0,i))/factorial(i));
    }
    return e * sum;
}

在 main.cpp 中

#include "e.hpp"
#include <iostream>
#include <cmath>

int main()
{
    E a;
    std::cout << "E calculated at x_0 = 1: " << a.computeE() << std::endl;
    std::cout << "E Calculated with std::exp: " << std::exp(1) << std::endl;
}

输出:
E calculated at x_0 = 1: 7.38752
E calculated with std::exp: 2.71828

当我更改为 x_0 = 0.
E calculated at x_0 = 0: 7.03102
E calculated with std::exp: 2.71828

我做错了什么?我是否错误地执行了泰勒级数?我的逻辑在某处不正确吗?

【问题讨论】:

  • 投反对票的人能解释一下他们的理由吗?
  • 您的阶乘函数容易溢出。并且不要首先计算它:而是计算一个运行除数。计算更稳定,速度更快。
  • 另外,你为什么使用e的硬编码值,并用std::pow来提高它,而不是使用std::exp
  • @Bathsheba,你能给我一个运行除数的例子吗?
  • @AlgirdasPreidžius,我试图在 x_0 等于 1 时逼近 e^x。我需要事先知道 e,因为 x_0 等于 1 时的泰勒级数展开式是:e^x_0 * n=0 到 inf (x-x_0)^n/n! 的总和。我提出它,所以我已经有了第一个任期。

标签: c++ math taylor-series


【解决方案1】:

是的,你的逻辑在某处不正确。

就像 Dan 所说,每次计算阶乘时,您都必须将 fact 重置为 1。您甚至可以将其设置为 factorial 函数的本地。

computeE 的返回语句中,您将总和乘以e,您不需要这样做。总和已经是 e^x 的泰勒近似值了。

关于0 的 e^x 的泰勒级数是 sum _i=0 ^i=infinity (x^i / i!),所以 x_0 在你的程序中确实应该是 0。

从技术上讲,当 x_0=0 时,computeE 会为 sum 计算正确的值,但这有点奇怪。泰勒系列从i=0 开始,但你以i=1 开始循环。但是,泰勒级数的第一项是x^0 / 0! = 1,您将sum 初始化为std::pow(e, x_0) = std::pow(e, 0) = 1,所以它在数学上是有效的。

(当你有x_0 = 1时,你的computeE函数计算了sum的正确值。你将sum初始化为std::pow(e, 1) = e,然后 for 循环根本没有改变它的值,因为 x - x_0 = 0。)

但是,正如我所说,在任何一种情况下,您都不需要在 return 语句中将其乘以 e

我会将computeE 代码更改为:

double E::computeE()
{
    sum = 0;
    for(int i = 0; i < N; ++i)
    {
        sum += ((std::pow(x-x_0,i))/factorial(i));
        cout << sum << endl;
    }
    return sum;
}

并设置x_0 = 0

【讨论】:

  • 感谢您的回答。我想我以这种方式开始它的原因是因为我想在 x_0 = 1 而不是 x_0 = 0 时计算 e^x。这将泰勒级数从 n=0 的总和变为无穷大 x^n/n!到 e 乘以 n=0 到无穷大 (x-1)^n/n 的总和!我想不出任何其他方法来做到这一点。并为此格式道歉。我不确定 SO 是否支持数学符号。
  • 如果您尝试使用大约 1 的泰勒级数计算 e,那么正如您所说,每个项都乘以 e,因此您需要已经知道 e.
  • 好的,这就是我似乎在挣扎的地方。那我不应该删除e 吗?当我删除e 时,我得到输出2.71799,我相信我要做的只是近似e^x。当我设置 x_0 = 0 时,我得到了预期的输出 2.71828。那么这仍然是错误的吗?
  • @jcarpenter e^x0 准确地说,因为它是参数化的
【解决方案2】:

每次计算阶乘时,"fact" 必须重置为 1。它应该是一个局部变量而不是一个类变量。

如果“fact”是一个类变量,并且您让“factorial”将其更改为 6,这意味着当您第二次调用“factorial”时它将具有 6 值。而这只会变得更糟。删除您对“事实”的声明并改用它:

int E::factorial(int n)
{
    int fact = 1;
    if(n == 0) return 1;
    for(int i = 1; i <= n; ++i)
    {
        fact = fact * i;
    }

    return fact;
}

【讨论】:

  • 我已经改变了它,所以 factint E::factorial(int n) 的顶部,我仍然收到 7.38752 的相同输出。那么,您能向我解释一下为什么在它似乎对输出没有影响的情况下需要进行这种更改吗?我希望这个问题没有得到很好的解决。
  • 在阶乘函数体内移动int fact = 1;。否则,您将使用以前的 fact 值作为下一个函数调用的起始值
  • @MBo,我已经正式把它移过来了。谢谢你的澄清。
【解决方案3】:

少写代码。

不要使用阶乘。

这里是Java。将其转换为 C++ 应该没有问题:

/**
 * @link https://stackoverflow.com/questions/46148579/trying-to-compute-ex-when-x-0-1
 * @link https://en.wikipedia.org/wiki/Taylor_series
 */
public class TaylorSeries {

    private static final int DEFAULT_NUM_TERMS = 50;

    public static void main(String[] args) {
        int xmax = (args.length > 0) ? Integer.valueOf(args[0]) : 10;
        for (int i = 0; i < xmax; ++i) {
            System.out.println(String.format("x: %10.5f series exp(x): %10.5f function exp(x): %10.5f", (double)i, exp(i), Math.exp(i)));
        }
    }

    public static double exp(double x) {
        return exp(DEFAULT_NUM_TERMS, x);
    }

    // This is the Taylor series for exp that you want to port to C++
    public static double exp(int n, double x) {
        double value = 1.0;
        double term = 1.0;
        for (int i = 1; i <= n; ++i) {
            term *= x/i;
            value += term;
        }
        return value;
    }
}

【讨论】:

    猜你喜欢
    • 2021-02-03
    • 2021-01-24
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    相关资源
    最近更新 更多