C++ - テイラー展開 [ exp(x) ]!

Updated:


今回は \(e ^ {x}\)をテイラー展開を用いて計算する C++ アルゴリズム についてです。
※以下、一部 \(\TeX\) で記載

まず、

TAYLOR_EXPANSION_01

そして、

TAYLOR_EXPANSION_EXP_E_01

今回は C++ で実現することが目的なので、テイラー展開の詳細についてはここでは説明しません。
解析学の教科書等でご確認下さい。

以下、C++ によるサンプルソースです。

0. 前提条件

  • Scientific Linux 6.3 (64bit) での作業を想定。
  • g++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4)

1. C++ ソース作成

今回作成した C++ ソースは以下のとおり。

  • C++ なのでオブジェクト指向な作りにしている。
  • 収束しない場合は最大200項計算するようにしている。
  • 今回計算した値と比較するため、C++ 標準の関数の値も出力している。
  • \(x=-50,\cdots,50\)を10刻みで計算している。
  • x < 0 の場合は、\(e ^ {-x}=1/e ^ x\)として計算。

File: taylor_expansion.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*********************************************
 * テイラー展開 ( exp(x) )
 *********************************************/
#include <iostream>  // for cout
#include <math.h>    // for exp(), fabs()
#include <stdio.h>   // for printf()

using namespace std;

/*
 * 計算クラス
 */
class Calc
{
    // 各種定数
    static const double eps = 1e-08;  // 精度

    // 各種変数
    double x;  // X 値
    double e;  // e 値
    double d;  // d 和
    double s;  // s 和
    int k;     // LOOP インデックス

    public:
        // テイラー展開
        void calcTaylor();
        // exp 計算
        double calcExp(double x);
};

/*
 * テイラー展開
 */
void Calc::calcTaylor()
{
  // x = -50 から 50 を 10 刻みで計算
  printf("    x      myexp(x)        exp(x)\n");
  for (x = -50; x <= 50; x += 10)
    printf("%5.1f%14.6g%14.6g\n", x, calcExp(x), exp(x));
}

/*
 * Exp 計算
 */
double Calc::calcExp(double x)
{
  // 変数初期化
  d = 1.0;
  s = 1.0;
  e = 1.0;

  // 最大200回ループ処理
  for(k = 1; k <= 200; k++) {
    d = s;                // d 和
    e = e * fabs(x) / k;  // e 値
    s += e;               // s 和
    // 打ち切り誤差
    if (fabs(s - d) / fabs(d) < eps) {
      if (x > 0)
        return s;
      else
        return 1.0 / s;
    }
  }

  // 収束しない時
  return 0.0;
}

/*
 * メイン処理
 */
int main()
{
    try
    {
        // 計算クラスインスタンス化
        Calc objCalc;

        // テイラー展開
        objCalc.calcTaylor();
    }
    catch (...) {
        cout << "例外発生!" << endl;
        return -1;
    }

    // 正常終了
    return 0;
}

2. C++ ソースコンパイル

$ g++ taylor_expansion.cpp -o taylor_expansion

何も出力されなければ成功。

3. 実行

$ ./taylor_expansion
    x      myexp(x)        exp(x)
-50.0   1.92875e-22   1.92875e-22
-40.0   4.24835e-18   4.24835e-18
-30.0   9.35762e-14   9.35762e-14
-20.0   2.06115e-09   2.06115e-09
-10.0   4.53999e-05   4.53999e-05
  0.0             1             1
 10.0       22026.5       22026.5
 20.0   4.85165e+08   4.85165e+08
 30.0   1.06865e+13   1.06865e+13
 40.0   2.35385e+17   2.35385e+17
 50.0   5.18471e+21   5.18471e+21

標準関数と同じ結果が得られた。


数学はおもしろいけど、コンピュータで実証するというのもおもしろいです。

※ちなみに最近の当方の C++ アルゴリズムについての記事は、古い C によるアルゴリズムに関する書物を参考に C++ に移植した形態となっています。

以上。





 

Sponsored Link

 

Comments