Subsections

5 浮動小数点と数値計算

5.1 実数演算の誤差

実数では有限のビット数で表現されるため,2進数での桁数が無限に必要な場合はメモリー 中のデータには誤差が含まれる.この誤差を丸め誤差(rounding error)と言う.

C言語の倍精度実数型の精度は,およそ$ 10^{-16}$ である.この精 度よりも大きさの差(絶対値)が小さい2つの実数の和と差の演算はできない.加算や減算 を行っても,その小さい値は無視される.これを情報落ちと言う.

三角関数を計算する場合,以下のような級数を使う.

$\displaystyle \sin x$ $\displaystyle =x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\frac{x^9}{9!} -\frac{x^{11}}{11!}+\cdots$    
  $\displaystyle =\sum_{n=1}^{\infty}(-1)^{n+1}\frac{x^{2n-1}}{(2n-1)!}$ (5)

コンピューターでは無限級数を計算することはできない.これをきちんと計算するために は,無限界の計算回数が必要で,無限の時間がかかる.それに,精度が有限であるため, ある程度以下の計算は無意味である.そのため,精度内に計算が収まったら,計算を止め るようになっている.途中で計算を打ち切るので,この誤差を打ち切り誤差と言う.

5.2 二分法

二分法の考え方は単純であるが,非常に強力な方程式の近似解を求める方法である. 考え方の基本は,閉区間$ [a,\,b]$ で連続な関数$ f(x)$ の値が,

$\displaystyle f(a)f(b)<0$ (6)

ならば, $ f(\alpha)=0$ となる$ \alpha$ が区間$ [a,\,b]$ にある.これは,中間値の定理か ら保証される.こんなことを言わないまでもあたりまえである.ただ,連続な区間で適用 できることを忘れてはならない.

実際の数値計算は, $ f(a)f(b)<0$ であるような2点 $ a,\,b(a<b)$ から出発する. そして,区間$ [a,\,b]$ を2分する点$ c=(a+b)/2$ に対して,$ f(c)$ を計算を行う. $ f(c)f(a)<0$ ならば$ b$$ c$ と置き換え, $ f(c)f(a)>0$ ならば$ a$$ c$ と置き 換える.絶えず,区間$ [a,b]$ の間に解があるようにするのである.この操作 を繰り返して,区間の幅$ \vert b-a\vert$ が与えられた値 $ \varepsilon$ よりも小さく なったならば,計算を終了する.解へ収束は収束率1/2の一次収束という.

リスト6に実際のプログラム例を示す.このプログラムと先の説明で用いた変数との対応は,次の通りである.

$ a\rightarrow$ left
$ b\rightarrow$ riht
$ c\rightarrow$ mid
$ \varepsilon\rightarrow$ epsilon

リスト6 二分 法のプログラム(転載について)

   1 #include <stdio.h>
   2 #include <math.h>
   3 #include <stdlib.h>
   4 
   5 double func(double x)
   6 { 
   7     return x*cos(x)+sin(x)+exp(-x*x)+x*x-x-3;
   8 }
   9 
  10 
  11 double BinarySearch(void)
  12 {
  13     double left,mid,right,epsilon;
  14 
  15     epsilon=0.00001;
  16 
  17     left=-2.0;
  18     right=2.0;
  19 
  20     while(fabs(right-left)>epsilon)
  21     {
  22         mid=(left+right)/2.0;
  23 
  24         if(func(left)*func(mid)>=0.0)
  25             left=mid;
  26         else
  27             right=mid;
  28     }
  29     return left;
  30 }
  31 
  32 int main(void)
  33 {
  34     double d;
  35     d=BinarySearch();
  36     printf("方程式の解は%lf,"
  37             "そのときのfunc(x)は%lfです。\n",d,func(d));
  38     return EXIT_SUCCESS;
  39 }

5.3 練習問題

[1]
C言語の実数型を使った演算で生じる3つの誤差の名前を書け.
[2]
2分法(バイナリーサーチ)を用いて,方程式の近似解を求める原理を説明せ よ.

[転載について]
このページ中のリスト6のプログラムは,教科書として使用している以下の書籍
書名プログラミングの宝箱 アルゴリズムとデータ構造 ISBN4-7973-2419-8
著作者紀平拓男・春日伸弥
出版社ソフトバンク パブリッシング株式会社
から転載しました(ただし,一部変更している).この転載に関しては,著者と版元に許諾を得ています.



ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
2006-02-27


no counter