コンピュータ演習4

コンピュータ演習4
打ち切り誤差・情報落ち
有効数字
位取りの”0”を除いた意味のある数字です。
具体的には、
6.05 m・・・有効数字3桁
0.65 m・・・有効数字2桁
1.6 m ・・・有効数字2桁
1.60 m・・・有効数字3桁
などで、より有効数字をはっきりさせた表現は
0.65 =6.5×101
のように*.**×10**と表現したときの*.**で有効数
字の桁数が分かります。これが数字の精度となり
ます。
加減算
23 gのお菓子を1.5 gの袋に詰めると全部で何gになるでしょう
か。
23 g+1.5 g=24.5 g
答 24.5 g
としてしまいがちですが、“23 g”ということは“22.7 g”かもしれ
ないし、“23.1 g”かもしれません。もともとお菓子の方は小数
点以下の値はあやしいのですから、袋の方がいくら細かく測
定してあっても、答えも小数点以下は意味がありません。で
すから、小数第1位を四捨五入して、
23 g+1.5 g=24.5 g
答 25 g
5
とするのが正しいのです。つまり加減の場合は、一番粗い
(有効数字の末位が最高の)項で答えの有効数字がきまりま
す。
乗除算
縦1.3 m、横2.12 mの長方形の面積はいくらでしょうか。
1.3 m×2.12 m=2.756 m2
答 2.756 m2
としたくなるかもしれませんが、縦の長さの小数点以下第2位は不明です。ですから
1.3?
×)2.12
‐‐‐‐‐‐‐‐‐‐‐‐‐
26?
13?
26?
‐‐‐‐‐‐‐‐‐‐‐‐‐
2.7???
となって、答えの小数第2位以下は意味がないことがわかります。したがって、小数
第2位を四捨五入して
1.3 m×2.12 m=2.756 m2
答 2.8 m2
8
とするのが正しいのです。つまり乗除の場合、答えの有効数字の桁数は、各項の有
効数字のうち最小のものと同じになります。
打ち切り誤差
打ち切り誤差とは、本来無限に行われなけれ
ばならない計算を有限の範囲の計算で済ませ
ることによって生じる誤差のことである。
●無限級数による計算
●台形則による(積分)面積計算
など
打ち切り誤差(例)
計算機による数値微分(
#include<stdio.h>
#include<math.h>
float f(float x);
int main(void){
float a=3.141592654f/4.0f, h;
for(h=2.0f; h > 1.0f/2048.0f; h/=2.0f ){
printf("h = %f, df = %f¥n", h,(0.5f*f(a+h)‐0.5f*f(a‐h))/h);
}
return 0;
}
float f(float x){
return cos(sin(x));
}
)
真の値:‐0.4593626849327
【実行結果】
h = 2.000000, df = 0.086948
h = 1.000000, df = ‐0.208975
h = 0.500000, df = ‐0.386740
h = 0.250000, df = ‐0.440534
h = 0.125000, df = ‐0.454613
h = 0.062500, df = ‐0.458172
h = 0.031250, df = ‐0.459065
h = 0.015625, df = ‐0.459290
h = 0.007813, df = ‐0.459347
h = 0.003906, df = ‐0.459358
h = 0.001953, df = ‐0.459366
h = 0.000977, df = ‐0.459351
続行するには何かキーを押してください . . .
打ち切り誤差(対策)
• 倍精度(double)にして計算する。
• 打ち切る個数を多くする。
• 打ち切り誤差が起こるように見えて、実は情
報落ちにより正しい数値が得られていない場
合もあるので注意。
桁落ち
同じくらいの大きさの数の差をとると、有効桁数
が減少することを桁落ちという。桁落ちした数値
を用いてそのまま計算を行うと、それ以降の数
値の有効桁数は減少したままである。
1001
1000
31.6386
6桁
31.6228
6桁
0.0158
3桁
桁落ち(例)
2次方程式の解
#include<stdio.h>
#include<math.h>
真の解: 2560.9953143217,
0.0046856782333387
int main(void){
float x1, x2, D;
float a=1.0f, b=‐2561.0f, c=12.0f;
D = b * b ‐4.0f * a * c;
x1 = (‐b + sqrt(D))/2.0f/a;
x2 = (‐b ‐ sqrt(D))/2.0f/a;
printf("%d x^2 + (%d)x + (%d) = 0 の解は
¥n",(int)a,(int)b,(int)c);
printf("x1=%f, x2=%f¥n",x1,x2);
printf("である¥n");
return 0;
}
【実行結果】
1 x^2 + (‐2561)x + (12) = 0 の解は
x1=2560.995361, x2=0.004639
である
続行するには何かキーを押してください . . .
数字で計算すると・・・
桁落ち!
解決法!
解と係数の関係を使い、大きい解から小さい解
を求める!
を用いると
桁落ち!
を用いると
桁落ち(対策)
• 倍精度(double)で計算する。
• 引き算をしない(数式を変形し、引き算がでな
いように工夫する)。
演習
1.例題の2次方程式の解を求めるプログラムを正しい解が求められるよう
修正しなさい(変数や定数等はfloat型で計算してください)。
2.微分の近似公式
を用いて
の
の値を求めよ
(変数や定数等はfloat型で計算してください) 。
3.
のとき、
の値を求めよ
(変数や定数等はfloat型で計算してください)。