数値計算のねらいは,できるだけ精確・高速に解を得ることである.誤差と収束性,安定性が数値計算のツボとなる.ここでは,丸め誤差(roundoff error)について見ておこう.打ち切り誤差(truncation error),収束性と安定性については次章でみる.
32bitのCPUでは1ワードは4byte(4x8bits).符号に1bit必要なので,2^(31)-1が1ワードで表現できる最大整数.実数も浮動小数点で表わす場合は1ワードを基本として,以下のような式で表わされる.
s x f x B^(e-E) |
---|
s is the sign bit(符号ビット:正負の区別を表す) |
e is the biased exponent(指数) |
f is the fraction portion of the number(仮数部) |
real: s=1, e=8, f=23 |
double precision: s=1, e=11, f=52 |
Bはbase(基底)で通常は2,Eはbias(下駄)と呼ばれる.64bitのCPUでは1ワードは8bytesになり,realも64bitになるが,現在ではあまりこうは言わないようだ.上記はIEEE規格で現在の主流.
小さい数を足したときにマシンがそれを認識できなくなる限界.
#include <stdio.h> int main(void){ float e,w; e=1; w=1+e; while(w>1){ printf("%-15.10g %-15.10g %-15.10g\n",e,w,w-1); e/=2; w=1+e; } }
1 2 1 0.5 1.5 0.5 0.25 1.25 0.25 0.125 1.125 0.125 0.0625 1.0625 0.0625 0.03125 1.03125 0.03125 0.015625 1.015625 0.015625 0.0078125 1.0078125 0.0078125 0.00390625 1.00390625 0.00390625 0.001953125 1.001953125 0.001953125 0.0009765625 1.000976562 0.0009765625 0.00048828125 1.000488281 0.00048828125 0.000244140625 1.000244141 0.000244140625 0.0001220703125 1.00012207 0.0001220703125 6.103515625e-05 1.000061035 6.103515625e-05 3.051757812e-05 1.000030518 3.051757812e-05 1.525878906e-05 1.000015259 1.525878906e-05 7.629394531e-06 1.000007629 7.629394531e-06 3.814697266e-06 1.000003815 3.814697266e-06 1.907348633e-06 1.000001907 1.907348633e-06 9.536743164e-07 1.000000954 9.536743164e-07 4.768371582e-07 1.000000477 4.768371582e-07 2.384185791e-07 1.000000238 2.384185791e-07 1.192092896e-07 1.000000119 1.192092896e-07
0.723657 -0.723649 --------- 0.000008
72365.7 + 1.23859126 --------- 72366.9
72365.7 + 0.001 --------- 72365.7
#include <stdio.h> int main(void){ float a,b,c; double x,y,z; a=1.23456789; printf(" a= %17.10f\n",a); b=100.0; c=a+b; printf("%20.10f %20.10f %20.10f\n",a,b,c); x=(float)1.23456789; y=(double)100; z=x+y; printf("%20.12e %20.12e %20.12e\n",x,y,z); x=(double)1.23456789; y=(double)100; z=x+y; printf("%20.12e %20.12e %20.12e\n",x,y,z); return 0; }
#include <stdio.h> #include <math.h> int main(void){ double a,b,c,xp,xm,xpp,xpm; a=1; b=-10000000; c=1; xp=(-b+sqrt(pow(b,2)-4.0*a*c))/(2.0*a); xm=(-b-sqrt(pow(b,2)-4.0*a*c))/(2.0*a); xpp=2*c/(-b-sqrt(pow(b,2)-4.0*a*c)); xpm=2*c/(-b+sqrt(pow(b,2)-4.0*a*c)); printf("%25.15f %25.15f \n%25.15f %25.15f\n",xp,xm,xpp,xpm); return 0; }
名称 | Fortran | C |
---|---|---|
整数 | integer | int |
2倍長整数 | integer*8 | long int |
単精度実数 | ireal | float |
倍精度実数 | real*8 | double |
double precision | ||
単精度複素数 | complex | |
倍精度複素数 | complex*16 |
Fortranの各行のあたまには通常6文字分の空白をあける.そこになにかが表記されているときは,注釈,継続行,および参照ラベルを意味する.注釈は第1桁目に文字*あるいは文字cがあると注釈行となる.6ケタ目に0以外の文字がある場合,この行は継続行とみなされる.参照ラベルは,すぐ後に出てくる入出力の書式指定や,制御文に使われる.
scanfとprintfに対応.
変数の型 | Fortran | C |
---|---|---|
整数 | 3i4 | %4i %4i %4i, %ld |
実数 | f10.5 | %10.5f |
浮動小数点表示 | d10.5 | %10.5e |
write(*,*)あるいはread(*,*)だと書式指定なしでデフォルトへの出力あるいは入力となる.
read(5,100) a,b,c write(6,101) a,b,c 100 format(3f10.5) 101 format("Input:",2f10.5," Answer:",f10.5)
演算 | Fortran | C |
---|---|---|
加算 | + | + |
減算 | - | - |
掛算 | * | * |
割り算 | / | / |
べき乗 | ** | pow(double, double) |
関数 | 内容 |
---|---|
sqrt(x) | xの平方根 |
abs(x) | xの絶対値 |
sin(x) | xの正弦,xはラジアン単位 |
cos(x), tan(x) | xの余弦,正接,xはラジアン単位 |
exp(x) | xのe乗 |
log(x) | xの自然対数 |
log10(x) | xの常用対数 |
int(x) | 実数値を整数値に変換する |
real(x) | 整数値を実数値に変換する |
mod(i,j) | i/jの整数剰余 |
繰り返しなどの範囲は参照ラベルで指定.
if (条件文) then 実行文 else 実行文 end if
do 100 i=1,10,2 実行文 100 continue 1ずつ上がるときは最後の2を省略.Cでは for (i=1; i<=10; i+=2){ 実行文 }
do 200 while (条件文) 実行文 200 end do
表記(1) | 表記(2) | 意味 |
---|---|---|
.eq. | == | equals |
.ge. | >= | greater or equal |
.gt. | > | greater than |
.le. | <= | less than or equal |
.lt. | < | less than |
.ne. | /= | not equal |
意味 | Fortran | Cでの表記 |
---|---|---|
否定(negation)演算子 | .not. | !a |
and演算子 | .and. | (a&&b) |
or演算子 | .or. | (a || b) |