2017-08-29 25 views
0

指数近似代码基于裁缝系列https://en.wikipedia.org/wiki/Taylor_series围绕零可以很好地用于输入,但移动在两个方向上更远时是完全无用的。下面是我的小测试代码的输出,相比的std :: EXP结果,并在边境的错误是巨大的内-12至12的范围和打印错误计算输入EXP。对于-12输入例如误差约为高达148255571469%:指数近似不是小的或大的输入良好

in = -12 error = 148255571469.28% 
in = -11.00 error = 18328703925.31% 
in = -10.00 error = 2037562880.10% 
in = -9.00 error = 199120705.27% 
in = -8.00 error = 16588916.06% 
in = -7.00 error = 01128519.76% 
in = -6.00 error = 00058853.00% 
in = -5.00 error = 00002133.29% 
in = -4.00 error = 00000045.61% 
in = -3.00 error = 00000000.42% 
in = -2.00 error = 00000000.00% 
in = -1.00 error = 00000000.00% 
in = 0.00 error = 00000000.00% 
in = 1.00 error = 00000000.00% 
in = 2.00 error = 00000000.00% 
in = 3.00 error = 00000000.00% 
in = 4.00 error = 00000000.03% 
in = 5.00 error = 00000000.20% 
in = 6.00 error = 00000000.88% 
in = 7.00 error = 00000002.70% 
in = 8.00 error = 00000006.38% 
in = 9.00 error = 00000012.42% 
in = 10.00 error = 00000020.84% 
in = 11.00 error = 00000031.13% 
in = 12.00 error = 00000042.40% 

我需要一个误差近似小于跨越尽可能大的范围内1%的误差。任何想法如何实现这一目标?

我的小测试,代码如下:

#include <cmath> 
    #include <iostream> 
    #include <iomanip> 

    double my_exp(double x) //based on https://en.wikipedia.org/wiki/Exponential_function 
    { 
     double res = 1. + x, t = x; 
     unsigned long factorial = 1; 
     for (unsigned char i = 2; i <= 12; ++i) 
     { 
      t *= x, factorial *= i; 
      res += t/factorial; 
     } 
     return res; 
    } 

    int main(int argc, char* argv[]) 
    { 
     for (double in = -12; in <= 12; in += 1.) 
     { 
      auto error = std::abs(my_exp(in) - std::exp(in)); 
      auto percent = error * 100./std::exp(in); 
      std::cout << "in = " << in << " error = " 
       << std::fixed << std::setw(11) << std::setprecision(2) 
       << std::setfill('0') << percent << "%" << std::endl; 
     } 
     return 0; 
    } 

从看似类似的问题的解决方案从“大约E 1 X” Approximate e^x不解决这个问题:基于雷米兹和帕德逼近

  • 解决方案只有有限的范围内提供准确度(https://stackoverflow.com/a/6985347/5750612
  • E 1 X = 2×/ LN(2)归结POW的toapproximation和我无法找到精确的一个
  • 裁缝系列不为小和大的投入工作
  • expf_fast溶液产生更均匀的误差在所有范围内,但它仍然是过大(〜在范围的端部20%)
+0

的可能的复制[大致E 1 X](https://stackoverflow.com/questions/6984440/approximate-ex) – jodag

回答

0

的所述一个发现与泰勒展开近似简单的方法是检查收敛速度只是增加一个新的更高的期限和确认结果。

这里是我的C++代码,以支持上述观点。

#include <iostream> 
#include <cmath> 

double my_exp(const double x, const double x0 = 0, const double ncut = 1e-3) 
{ 
    double res = 1.; 
    double addterm = (x - x0); 
    size_t norder = 1; 

    while(true) 
    { 
     double res_update = res + addterm; 
     if(std::abs(res_update - res)/std::abs(res) < ncut){ 
      break; 
     } 
     norder += 1; 
     addterm *= (x - x0)/norder; 
     res = res_update; 
    } 

    return res; 
} 


int main(int argc, char* argv[]) 
{ 
    const double x = std::atof(argv[1]); 
    const double approxi = my_exp(x); 

    const double exactResult = std::exp(x); 

    std::cout<<"approxi : "<< approxi<<std::endl; 
    std::cout<<"exact : "<< exactResult<<std::endl; 

    std::cout<<"err: "<< (1 - std::abs(approxi/exactResult))*100 <<std::endl; 

    return 0; 
} 
+0

这一次似乎很好地工作。当使用我的测试代码时,结果是所有范围内的百分之几: in = -12 error = 00000000.03% in = -11.00 error = 00000000.05% in = -10.00 error = 00000000.02% in = -9.00 error = 00000000.04% 在= -8.00误差= 00000000.07% 在-7.00 =错误= 00000000.03% ... 在= 7.00误差= 00000000.10% 在= 8.00误差= 00000000.16% 中= 9.00误差= 00000000.11% in = 10.00 error = 00000000.16% in = 11.00 error = 00000000.10% in = 12.00 error = 00000000.15% – picant

相关问题