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

Updated:


先日、\(e ^ {x}\)をテイラー展開を用いて計算する C++ アルゴリズム について紹介しました。

今日は、\(\cos x\)をテイラー展開を用いて計算してみました。
※以下、一部 \(\TeX\) で記載

TAYLOR_EXPANSION_COS_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=0,\cdots,180\)を10刻みで計算している。

File: taylor_xxpansion_cos.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
92
93
94
95
96
/*********************************************
 * テイラー展開 ( cos(x)) )
 *********************************************/
#include <iostream>  // for cout
#include <math.h>    // for cos()
#include <stdio.h>   // for printf()

using namespace std;

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

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

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

/*
 * テイラー展開
 */
void Calc::calcTaylor()
{
  // ラジアン値計算
  rd = pi / 180;

  // x = 0 から 180 を 10 刻みで計算
  printf("    x      mycos(x)        cos(x)\n");
  for (x = 0; x <= 180; x += 10)
    printf("%5.1f%14.6f%14.6f\n", x, calcCos(x * rd), cos(x * rd));
}

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

  // x の値が 0 から 2π の範囲外の場合、0 から 2π に収める
  x = fmod(x, 2 * pi);

  // 最大200回ループ処理
  // ( ただし、偶数項は 0 なので除外 )
  for(k = 1; k <= 200; k = k + 2) {
    d = s;                           // d 和
    e = -e * x * x / (k * (k + 1));  // 各項の値
    s += e;                          // s 和
    // 打ち切り誤差
    if (fabs(s - d) / fabs(d) < eps)
        return(s);
  }

  // 収束しない時
  return(9999.0);
}

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

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

    // 正常終了
    return 0;
}

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

$ g++ taylor_expansion_cos.cpp -o taylor_expansion_cos

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

3. 実行

$ ./taylor_expansion_cos
    x      mycos(x)        cos(x)
  0.0      1.000000      1.000000
 10.0      0.984808      0.984808
 20.0      0.939693      0.939693
 30.0      0.866025      0.866025
 40.0      0.766044      0.766044
 50.0      0.642788      0.642788
 60.0      0.500000      0.500000
 70.0      0.342020      0.342020
 80.0      0.173648      0.173648
 90.0      0.000000      0.000000
100.0     -0.173648     -0.173648
110.0     -0.342020     -0.342020
120.0     -0.500000     -0.500000
130.0     -0.642788     -0.642788
140.0     -0.766044     -0.766044
150.0     -0.866025     -0.866025
160.0     -0.939693     -0.939693
170.0     -0.984808     -0.984808
180.0     -1.000000     -1.000000

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

その他

ちなみに、

TAYLOR_EXPANSION_SIN_01

など、色々計算可能です。


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

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

以上。





 

Sponsored Link

 

Comments