• 検索結果がありません。

● 講義資料

N/A
N/A
Protected

Academic year: 2021

シェア "● 講義資料"

Copied!
8
0
0

読み込み中.... (全文を見る)

全文

(1)

● 講義資料

▼ 講義予定

浮動小数点数とは何か(先週の例を元に)

自然対数の底 eの近似値の計算

● 前回の講義のまとめ

二分法を使って

2の近似値を計算した.

二分法で

2 の近似値を計算するためのアルゴリズムは以下の通り.

1. l0= 0,u0= 2,k= 0とおく.

2. l=lk,u=uk とおき,c= (l+r)/2 を計算する.

3. c2<2 ならばlk+1=c,rk+1=rk,c2>2ならばlk+1 =lk,rk+1 =c とおく.

4. k:=k+ 1とおき, 2に戻る.

この方法は,k が指定の回数になったときに終了させない限り,無限ループに陥ってしまう.

このアルゴリズムは区間縮小法に基づくものであるが,f(x) =x2−2に対して,中間値の定理を適 用していると考えてもよい. すなわち, 連続関数f : [a, b]−→Rが,区間[a, b]上で単調増加であり, f(a)<0,f(b)>0 を満たしているとき,以下の二分法で,区間[a, b]に一意的に存在するf(x) = 0 の解xに収束する数列{xk} をつくることができる.

1. l0=a,r0=b,k= 0とおく.

2. xk= (lk+rk)/2 を計算する.

3. f(xk)<0ならばlk+1=xk,rk+1=rk,f(xk)>0ならばlk+1 =lk,rk+1 =xk とおく.

4. k:=k+ 1とおき, 2に戻る.

この時,すべてのkについてf(lk)<0,f(rk)>0 であるので,x∈[lk, rk]が成り立つので,

|x−xk| ≤1

2|rk−lk|= 2(k+1)|b−a| が成り立つ. よって,xk x に収束する.

この二分法において,数学的にはf(xk) = 0となる可能性がある. しかし,コンピュータによるプロ グラムを考える場合には,f(xk)が演算誤差の範囲内で 0に近いときにプログラムを停止して, その ときの xk x の近似値と考える. 逆に言えば, x∈[a, b] において, f(x)の値を演算誤差が少な い状況で計算可能な関数 f にしか,この二分法を適用することはできない.

▼ 前回の計算例

前回のプログラム1(example_01_1.c)では,繰り返し回数を指定した.

2を求めるためには, 53 回の繰り返し終了時が最も近似の精度が良くなっていたはず.

(2)

★ プログラム例1

(example_02_1.c)

/* 二分法を用いて Sqrt(2) の値を計算する */

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#define EPSILON (1.0E-15) void calc_sqrt(double x) ;

int main(int argc, char **argv) {

if (argc > 1) calc_sqrt(atof(argv[1])) ; return 0 ;

}

void calc_sqrt(double x) {

double lower, upper, square_root ;

lower = 0.0 ; upper = x ;

square_root = (lower+upper)/2.0 ; while(fabs(lower-upper) > EPSILON) {

square_root = (lower + upper)/2.0 ;

if (square_root*square_root > x) upper = square_root ; else lower = square_root ;

printf("%e\n", fabs(lower-upper)) ; }

printf("%e\n", square_root) ; return ;

}

このプログラムは,コマンドライン引数に数値xを与えて,√xの近似値を二分法で計算する. ただ し,このプログラムもxの値によっては停止しない.

ループ終了条件は,|l−r| ≤ǫであり,ǫの値はEPSILONで与えられている.

• x= 2.0の時には,プログラムは終了するが,x= 200.0の時には,プログラムは終了しない. すなわ

ち,プログラム終了条件として,|l−r|を判定基準することは間違いであることがわかる.

(3)

★ プログラム例2

(example_02_2.c)

/* 二分法を用いて Sqrt(2) の値を計算する */

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#define EPSILON (4.0E-16) void calc_sqrt(double x) ;

int main(int argc, char **argv) {

if (argc > 1) calc_sqrt(atof(argv[1])) ; return 0 ;

}

void calc_sqrt(double x) {

double lower, upper, square_root ; double x0 = x ;

lower = 0.0 ; upper = x ; square_root = x ;

while(fabs(lower-upper) > EPSILON*fabs(square_root)) { square_root = (lower + upper)/2.0 ;

if (square_root*square_root > x) upper = square_root ; else lower = square_root ;

printf("%e %e\n", fabs(lower - upper), fabs((lower - upper)/square_root)) ; }

printf("%.12e %.12e\n", square_root,

fabs(square_root*square_root - x0)/square_root) ; return ;

}

例1を書き換えて,ループ終了条件として, |l−r| ≤ǫαと設定した. (ǫ= 4.0×1016はその時 点での近似値)

この場合,x= 2.0,x= 20.0,x= 200.0,x= 5.0×10300,x= 5.0×10−300など,すべての代入可能 な数値に対してプログラムが停止し,求めたx >1.0の場合には,

xは「ほぼ」望ましい近似値を 持っていることがわかる.

したがって,近似の判断基準として|l−r|< ǫαは適切なものであると考えられる.

(4)

– %f: 通常の12.345などと表示する – %e: 12.3451.2345E+02と表示する.

– %.Neとすると,小数点以下N桁を表示する

– %M.Neとすると,全体でM桁,小数点以下N桁を表示する(+M+は省略可能)これ以外にも書式指定があるので,それらはprintf関数のマニュアルを参照

一般に,ある値xの近似値xが与えられたとき, – ǫ=|x−x|を「絶対誤差」と呼び,

– |x−x|=ǫ|x|となるǫを「相対誤差」と呼ぶ.

実際の計算の相対誤差は, いくら小さくてもǫ∼10−16 程度にしかならないので, %e表示の時に意 味のある桁は,高々15桁である. (もっと長い桁を表示させることは可能であるが, 意味のない数 値が並ぶだけである)

▼ 自然対数の底の近似値を求める

以下の図は, (1 + 1/n)nを計算して,eの近似値を求めた例である.(eと近似値の値との絶対誤差を表 示している)

1e-08 1e-07 1e-06 1e-05 0.0001 0.001 0.01 0.1 1

10 100 1000 10000 100000 1e+06 1e+07 1e+08 1e+09 1e+10

(5)

★ プログラム例

(example_02_3.c)

/* double を用いて (1.0 + 1.0/n)^n を計算して, e との誤差を調べる */

#include <stdio.h>

#include <math.h>

#define MAX (10)

double power(double k, unsigned long n) ;

int main(int argc, char **argv) {

unsigned long n ; int i ;

double e ; n = 10 ;

for(i=0;i<MAX;i++) {

e = power(1.0+1.0/n, n) ;

printf("%lu %.14e\n", n, fabs(e - M_E)) ; n *= 10 ;

}

return 0 ; }

/* マジメに n 回の乗算を行う */

double power(double k, unsigned long n) {

double x = 1.0 ; unsigned long i ;

for(i=0;i<n;i++) x *= k ; return x ;

}

このプログラムでは,n= 10からn= 1010まで,n10倍しながら, (1 + 1/n)n を計算している.

その際 nとしてunsigned long型変数を使う必要がある. int型変数では,n= 1010までは計算 できない.

(6)

パラメータ 単精度 倍精度 4倍精度

N 8 11 15

M 24 53 113

ビット長 32 64 128

最大指数 +127 +1023 +16383

最小指数 −126 −1022 −16382

バイアスb 127 1024 16383

ǫM = 21M 223 252 2111

1.19×107 2.22×1016 3.85×1034

ǫM = 2M 224 253 2112

5.96×10−8 1.11×10−16 1.92×10−34

x= (−1)s(1 +

M−1X

j=1

fj2j)×2eb, e=

NX−1

k=0

ek2k, b=

NX−2

k=0

2k. (1)

いずれの場合にでも,

全てのk に対してek = 1ならば「オーバフロー」,

全てのk に対してek = 0ならば±0または「非正規数」

を示す.

仮数部2桁,指数部 −1≤e≤1 の2進浮動小数点数で正確に表示可能な値

0=0.00

q

1/8=0.01×21

a

2/8=0.10×21

a

3/8=0.11×21

a

1/8=0.01×21

a

2/8=0.10×21

a

3/8=0.11×21

a

4/8=1.00×21

q

4/8=1.00×21

q

5/8=1.01×21

q

5/8=1.01×21

q

6/8=1.10×21

q

6/8=1.10×21

q

7/8=1.11×21

q

7/8=1.11×21

q

4/4=1.00×20

q

4/4=1.00×20

q

5/4=1.01×20

q

5/4=1.01×20

q

6/4=1.10×20

q

6/4=1.10×20

q

7/4=1.11×20

q

7/4=1.11×20

q

4/2=1.00×21

q

4/2=1.00×21

q

5/2=1.01×21

q

5/2=1.01×21

q

6/2=1.10×21

q

6/2=1.10×21

q

7/2=1.11×21

q

7/2=1.11×21

q

Underflow

subnormal

e=−1

e=−1 e= 0

e= 0

e= 1 e= 1

-

overflow

overflow

この浮動小数点数の体系で表現できる数は,図のなかの黒円で示したものに限られる. , “subnormal”と示した数は,有効桁が少なくなっていることに注意.

したがって, 1/2 + 1/8 = 5/8と正確に計算することが可能であるが, 1/2 + 1/16は正確 な計算ができないことがわかる.

(7)

二分法による

2の計算経過. 初期区間[0,2], c1 = 1.0

1 00111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 2 00111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 3 00111111 11110100 00000000 00000000 00000000 00000000 00000000 00000000 4 00111111 11110110 00000000 00000000 00000000 00000000 00000000 00000000 5 00111111 11110111 00000000 00000000 00000000 00000000 00000000 00000000 6 00111111 11110110 10000000 00000000 00000000 00000000 00000000 00000000 7 00111111 11110110 11000000 00000000 00000000 00000000 00000000 00000000 8 00111111 11110110 10100000 00000000 00000000 00000000 00000000 00000000 9 00111111 11110110 10110000 00000000 00000000 00000000 00000000 00000000 10 00111111 11110110 10101000 00000000 00000000 00000000 00000000 00000000 11 00111111 11110110 10100100 00000000 00000000 00000000 00000000 00000000 12 00111111 11110110 10100010 00000000 00000000 00000000 00000000 00000000 13 00111111 11110110 10100001 00000000 00000000 00000000 00000000 00000000 14 00111111 11110110 10100000 10000000 00000000 00000000 00000000 00000000 15 00111111 11110110 10100000 11000000 00000000 00000000 00000000 00000000 16 00111111 11110110 10100000 10100000 00000000 00000000 00000000 00000000 17 00111111 11110110 10100000 10010000 00000000 00000000 00000000 00000000 18 00111111 11110110 10100000 10011000 00000000 00000000 00000000 00000000 19 00111111 11110110 10100000 10011100 00000000 00000000 00000000 00000000 20 00111111 11110110 10100000 10011110 00000000 00000000 00000000 00000000 21 00111111 11110110 10100000 10011111 00000000 00000000 00000000 00000000 22 00111111 11110110 10100000 10011110 10000000 00000000 00000000 00000000 23 00111111 11110110 10100000 10011110 01000000 00000000 00000000 00000000 24 00111111 11110110 10100000 10011110 01100000 00000000 00000000 00000000 25 00111111 11110110 10100000 10011110 01110000 00000000 00000000 00000000 26 00111111 11110110 10100000 10011110 01101000 00000000 00000000 00000000 27 00111111 11110110 10100000 10011110 01100100 00000000 00000000 00000000 28 00111111 11110110 10100000 10011110 01100110 00000000 00000000 00000000 29 00111111 11110110 10100000 10011110 01100111 00000000 00000000 00000000 30 00111111 11110110 10100000 10011110 01100110 10000000 00000000 00000000 31 00111111 11110110 10100000 10011110 01100110 01000000 00000000 00000000 32 00111111 11110110 10100000 10011110 01100110 01100000 00000000 00000000 33 00111111 11110110 10100000 10011110 01100110 01110000 00000000 00000000 34 00111111 11110110 10100000 10011110 01100110 01111000 00000000 00000000 35 00111111 11110110 10100000 10011110 01100110 01111100 00000000 00000000 36 00111111 11110110 10100000 10011110 01100110 01111110 00000000 00000000 37 00111111 11110110 10100000 10011110 01100110 01111111 00000000 00000000 38 00111111 11110110 10100000 10011110 01100110 01111111 10000000 00000000 39 00111111 11110110 10100000 10011110 01100110 01111111 01000000 00000000 40 00111111 11110110 10100000 10011110 01100110 01111111 00100000 00000000 41 00111111 11110110 10100000 10011110 01100110 01111111 00110000 00000000 42 00111111 11110110 10100000 10011110 01100110 01111111 00111000 00000000 43 00111111 11110110 10100000 10011110 01100110 01111111 00111100 00000000 44 00111111 11110110 10100000 10011110 01100110 01111111 00111010 00000000 45 00111111 11110110 10100000 10011110 01100110 01111111 00111011 00000000 46 00111111 11110110 10100000 10011110 01100110 01111111 00111011 10000000 47 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11000000 48 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11100000 49 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11010000 50 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001000 51 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001100 52 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001110 53 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001101 54 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001100 55 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001100 56 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001100 57 00111111 11110110 10100000 10011110 01100110 01111111 00111011 11001100

(8)

またはマニアックな程度を表します. 多いほど難しいかマニアックかです.)

1. (★★★)プログラム2を入力し,種々のxの値に対して,ǫ= 4.0×1016を使うと,実際に√ x 近似値を求めることができることを確かめなさい.

2. (★★★)プログラム2の最後の行では, 入力値 x, 近似値αに対して,|x−α2|/α を求めている.

この値と, 実際の近似値の相対誤差 |√

x−α|/√

xとの関係を求めなさい. また,近似値を相対誤差 ǫで求めるためには,プログラム中のEPSILONの値をどのように決めればよいかを考えなさい.

3. (★)プログラム2は, 0< x <1 なる入力に対しては正しく

xの近似値を計算できない. どのよ うに修正すればよいか?

4. (★★)MacOSXunsigned int型整数は32 bits integerである. このことを用いて,unsigned int型整数として格納可能な自然数nの平方根の整数部分を求めるプログラムを書きなさい. また, その繰り返し回数が何回程度になるか?さらに,求めた値が,実際にnの平方根の整数部分になって いることを,確かめなさい.

5. (★★)MacOSX unsigned int 型整数は32 bits integer である. このことを用いて, 2つの

unsigned int 型整数の積と商を,乗算・除算を用いずに計算するプログラムを書きなさい. また,

unsigned int型変数の場合に,同様のプログラムを書きなさい.

6. (★★★)example_02_3.cを入力して,|(1 + 1/n)n−e|の値がnに対してどのように変化するか を調べなさい.

7. (★★★)example_02_3.cでは(1 + 1/n)n を計算するために, (1 + 1/n)n−1回乗算してい る. この部分を高速に計算できるように改良しなさい. この場合,nはもう少し大きなところまで計 算できるはずなので, n= 10k の形(または,n= 2k の形)でnとしてunsigned long型変数を 使ったときの限界の近くまで計算しなさい.

8. (★★★)example_02_3.cでは(1 + 1/n)n を計算するために, (1 + 1/n)n−1回乗算してい る. この部分をpow関数を利用して同様の計算を行いなさい. この場合も前問と同程度のnまで計 算しなさい.

参照

関連したドキュメント

が前スライドの (i)-(iii) を満たすとする.このとき,以下の3つの公理を 満たす整数を に対する degree ( 次数 ) といい, と書く..

この数字は 2021 年末と比較すると約 40%の減少となっています。しかしひと月当たりの攻撃 件数を見てみると、 2022 年 1 月は 149 件であったのが 2022 年 3

これはつまり十進法ではなく、一進法を用いて自然数を表記するということである。とは いえ数が大きくなると見にくくなるので、.. 0, 1,

点から見たときに、 債務者に、 複数債権者の有する債権額を考慮することなく弁済することを可能にしているものとしては、

本論文での分析は、叙述関係の Subject であれば、 Predicate に対して分配される ことが可能というものである。そして o

つまり、p 型の語が p 型の語を修飾するという関係になっている。しかし、p 型の語同士の Merge

としても極少数である︒そしてこのような区分は困難で相対的かつ不明確な区分となりがちである︒したがってその

・発電設備の連続運転可能周波数は, 48.5Hz を超え 50.5Hz 以下としていただく。なお,周波数低下リレーの整 定値は,原則として,FRT