在 e^x 的泰勒展开中获取 inf,但仅适用于小误差范围
Getting inf in a Taylor expansion for e^x, but only for small error bounds
我正在编写一个近似指数函数的程序,但我 运行 遇到了问题。对于 err
的小值,程序会搞砸并永远循环,每次都得到 inf 的近似值。随着输入的 x
越来越大,该程序似乎不能容忍越来越大的错误。它适用于 x=1
和 err=10e-5
。作为它何时不起作用的示例:x=3
它可以正常工作到 err=10e-4
但是当 err=10e-5
时它会导致 inf.
//This program approximates e^x at a given x to a given accuracy
#include<algorithm>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
inline void keep_window_open() {char ch; cin >> ch;}
class bad_entry{};
int fac(int a) //function to find factorial
{
int f=1; //covers 0!
for(int w=0; w<a; ++w)
{
f*=(a-w);
}
return f;
}
int main()
{
try
{
double x=0;
double ans=0;
double err=0;
int n=0;
cout << "What number do you want to expand around?\n";
cin >> x;
if(!cin){throw bad_entry{};}
cout << "What would you like the error to be within?\n";
cin >> err;
if(!cin){throw bad_entry{};}
double actual=exp(x);
while(n>=0)
{
ans += pow(x,n)/fac(n);
cout << "n=" << n << '\t' << "Approx: " << ans << '\t' << "Erro: " << abs(actual-ans) << '\n';
if(abs(actual-ans)<err)
{
keep_window_open();
return 0;
}
++n;
}
}
catch(bad_entry)
{
cout << "\nINVALID ENTRY\n";
return 0;
}
}
如果您编写的程序只打印 fac
以增加 n
值,您将得到:
n=1 fac=1
n=2 fac=2
n=3 fac=6
n=4 fac=24
n=5 fac=120
n=6 fac=720
n=7 fac=5040
n=8 fac=40320
n=9 fac=362880
n=10 fac=3628800
n=11 fac=39916800
n=12 fac=479001600
n=13 fac=1932053504 // Ups - wrong - should be 6227020800
n=14 fac=1278945280 // Ups - wrong
n=15 fac=2004310016 // Ups - wrong
因此 n
等于 13 时已经溢出。因此所有计算都会失败并给出奇怪的结果。
如果您将 fac
函数更改为使用 uint64_t
而不是 int
它会好一点,即溢出前更高的 n
。
你的 "while" 循环实际上是发散的;您正在递增计数器而不是递减。
此外,"pow" 函数本身实现为 "exp(y*ln(x))",这使得您的实现变得冗余、低效和不精确。
阶乘计算使得复杂度为 O(n2),这很糟糕。一个简单的不间断递增 for 循环,将精度标准作为其条件子句,并增量计算阶乘和整数 x 次幂就可以完成这项工作。
我正在编写一个近似指数函数的程序,但我 运行 遇到了问题。对于 err
的小值,程序会搞砸并永远循环,每次都得到 inf 的近似值。随着输入的 x
越来越大,该程序似乎不能容忍越来越大的错误。它适用于 x=1
和 err=10e-5
。作为它何时不起作用的示例:x=3
它可以正常工作到 err=10e-4
但是当 err=10e-5
时它会导致 inf.
//This program approximates e^x at a given x to a given accuracy
#include<algorithm>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
inline void keep_window_open() {char ch; cin >> ch;}
class bad_entry{};
int fac(int a) //function to find factorial
{
int f=1; //covers 0!
for(int w=0; w<a; ++w)
{
f*=(a-w);
}
return f;
}
int main()
{
try
{
double x=0;
double ans=0;
double err=0;
int n=0;
cout << "What number do you want to expand around?\n";
cin >> x;
if(!cin){throw bad_entry{};}
cout << "What would you like the error to be within?\n";
cin >> err;
if(!cin){throw bad_entry{};}
double actual=exp(x);
while(n>=0)
{
ans += pow(x,n)/fac(n);
cout << "n=" << n << '\t' << "Approx: " << ans << '\t' << "Erro: " << abs(actual-ans) << '\n';
if(abs(actual-ans)<err)
{
keep_window_open();
return 0;
}
++n;
}
}
catch(bad_entry)
{
cout << "\nINVALID ENTRY\n";
return 0;
}
}
如果您编写的程序只打印 fac
以增加 n
值,您将得到:
n=1 fac=1
n=2 fac=2
n=3 fac=6
n=4 fac=24
n=5 fac=120
n=6 fac=720
n=7 fac=5040
n=8 fac=40320
n=9 fac=362880
n=10 fac=3628800
n=11 fac=39916800
n=12 fac=479001600
n=13 fac=1932053504 // Ups - wrong - should be 6227020800
n=14 fac=1278945280 // Ups - wrong
n=15 fac=2004310016 // Ups - wrong
因此 n
等于 13 时已经溢出。因此所有计算都会失败并给出奇怪的结果。
如果您将 fac
函数更改为使用 uint64_t
而不是 int
它会好一点,即溢出前更高的 n
。
你的 "while" 循环实际上是发散的;您正在递增计数器而不是递减。 此外,"pow" 函数本身实现为 "exp(y*ln(x))",这使得您的实现变得冗余、低效和不精确。 阶乘计算使得复杂度为 O(n2),这很糟糕。一个简单的不间断递增 for 循环,将精度标准作为其条件子句,并增量计算阶乘和整数 x 次幂就可以完成这项工作。