10回目


数値演算のアルゴリズムのいろいろ
目的が同じ数値演算であっても様々なアルゴリズムが存在します.計算の原理が異なるもの,
同じような原理でも係数が異なるもの,など様々です.
理由はいろいろと考えられますが,

  1. 計算量を減らし,高速化を図る
  2. 計算誤差を減らし,精度向上を図る

ことが挙げられます.対象とする数式や条件によっては,アルゴリズムの得手不得手があるのが
通常であり,そのような特徴を理解したうえでシミュレーションを行うことが重要であると考えられ
ます.

ここで前回扱った,数値積分について扱ってみます.積分の原理説明そのままのような計算法に
台形則というものがあります.
下図の通り,対象とする関数の曲線をある区間ごとに区切り,区切られた点を結んだ直線による
台形の面積を足し合わせていくというものです.


               図1 台形則の原理

便宜上,上図では粗い区切りとしていますが,直線と曲線では軌跡が違うため,ひとつひとつの
台形の面積には誤差が生じます.上に凸の曲線の場合は台形の方が小さくなり,下に凸の場合
は,台形の方が大きくなる傾向になると言えばイメージがわきやすいと思います.

様々なアルゴリズムが存在するのは,こうした誤差を減らすためといえます.しかしながら,対象と
する方程式の係数などが大きい,極めて高次であることから,導関数の大きさが極めて大きくなる
場合などは誤差が生じる可能性があることは否めませんので,対象となる数式の性質を予め充分
に理解しておく必要はあります.

以下にいくつかのアルゴリズムのソースを置いておきます.

いずれも目的は同じですが,計算速度や精度が異なります.従って計算結果はそれぞれ少しずつ
異なります.

参考
PCやCPU(個人ユーザー向け)の変遷を紹介します.

Model/Type Maker CPU Frequency core
1983 PC-9801/F Intel 8086 8MHz 1
1990 Macintosh IIfx Motorola 68030 40MHz 1
1993 PC-9821Af Intel Pentium 60MHz 1
1997 Power Mac G3 IBM Power PC G3 300MHz 1
2000 DOS/V Intel Pentium4 400MHz 1
2003 DOS/V AMD Athron 64 1GHz 1
2006 DOS/V Intel Core2 Duo 1.8GHz 2
2010 DOS/V Intel Core i3 2.93GHz 2
2011 DOS/V AMD Phenom II X6 3.3GHz 6
2012 DOS/V Intel Core i7Extreme 3.3GHz 6
2013 DOS/V AMD Opteron 6376 2.3GHz 16

大雑把に調べたものですが,様々なアーキテクチャ(CPUの構造)が開発されクロックがどんどん
上がってきたた上に,近年はコア数が増え,並列処理的な処理がなされるようになってきました.
内部の処理,周囲に配置されたキャッシュメモリなどの改良によって,単純なクロック数以上の
進歩を続けています.
10数年以上昔は,数値シミュレーション,CGなどは一晩,あるいは数日かけて計算させていたもの
ですが,いまやそんなこともなくなっています.
古い文献などは,ヘリコプタの制御ができる処理能力はとても実現できないと書かれていましたが,
今となってはRT(実時間)をはるかに超える処理能力を持ったものとなっています.

以上のCPUの進歩とメモリの大容量化(30年前は1Mbyte以下)を考えるとプログラムの処理能力
については考え方が変わった面もありますが,組み込み機器(制御機器や家電,設備を動かす
CPU)については,省電力とコストの問題から,CPUも数十MHzオーダのものであり,メモリも大きく
ても十数Mbyte程度ですので,プログラムの効率化は今でも大変重要なのです.


課題1 先ず,x=t*t+3*t+2, x=10-exp(-2*t), x=10*sin(5*t)+5*sin(10*t-2)+2*sin(20*t-5)の関数
を作成せよ.なお関数の作り方は,x=f(t)とすれば,

double fnc(double t){
 return ;
}

とする.
例えば,時刻とともに増加する関数,x=tについては以下のようにすればよい.

double fnc(double t){
 return t;
}
提出にあたっては,関数3つをひとまとめのファイルにすればよい.fnc1,2,3等と区別すればよい.

課題2 上記課題の各関数について,台形則,シンプソン1/3の公式,ニュートン3/8の公式,
ガウスの公式で算出し結果を比較せよ.積分区間は任意で良い.適宜設定せよ.
ファイルは4つできればよい.結果は,コメント文として記述せよ.

メイン関数内での呼び出しは以下のようにすれば可能です.

main(){

 double (* f1)(double);

 f1=&fnc;


 intg_daikei(double f1(t), ?, ?, ?)
}


前回の解答