物理を題材にしたC入門 竹下徹
これから始めるCの練習コースはパリティーという雑誌に中村純さんがお書きになった「物理屋のためのFORTRAN入門」という文章のなかの教材として取り上げる物理現象をお借りしています。中村さんからも「使って結構」と返事をもらっています。
ではCプログラムの勉強です.さて初めは皆さんがプログラムについて何も知らないと仮定して始めます.ただしeditorは知っていて,プログラムを作るあるいは変更することはできるとして始めます.最低限のルールから始めましょう.つぎの例を見て下さい.
---------------------------------------------プログラム例1
#include <stdio.h>
main()
{
int me,res;
float her;
me = 2;
her=2.3 ;
res=me*her ;
printf(" result of you and her is = %d",res);
}
---------------------------------------------
このファイルをmeher.cとして保存したとしましょう.最後の .cは必ずつけて下さい。C-コンパイラーにこれがのプログラムで有ることを教えています。
C-コンパイラーを通して実行ファイルmeherを以下のようにして作ります.Cのプログラムは人間が皆さんが理解できる形(言語)で書かれていますが、計算機は理解できません。そこで、計算機にわかるようにプログラムを変換してやるにのがC-コンパイラーのお仕事です。
>はUNIXが画面上に入力待ち(prompt)であることを示し、みなさんの入力の必要はありません。
>cc meher.c -o meher
C-コンパイラーはccという実行形式のプログラムです。cc meher.c でccとmeher.cの間にはスペースが一つ入っています。さもないと、ccmeher.cというつながったプログラムを実行しようとしている事になります。-oの前と後も同じです。-oはoutput オプションの意味で、出力ファイル名をmeherにしなさいと言っています。結果はmeherを実行してつぎの様に得られます.
>meher
result of you and her is = 4>
なぜ4になったのでしょうか?
それはCの計算では整数型の変数(ここではmeとres)と実数型の変数(ここではher)があり両者はハッキリ区別されていることに注意してください.たとえば,実数型x実数型=実数型になりますし,実数型x整数型=実数型,整数型x整数型=整数型という演算をします.このプログラムでは,res=me*herという整数型x実数型の結果は実数型となるところをresという整数型変数に代入して,2x2.3=4.6 をまるめて4となっています.普通に我々が期待する結果と異なる理由を理解できましたか?
では正しい結果を得るように,皆さんはこのプログラムを改造してください.
ここで少しCの規則についてふれます.プログラムは main(){ から } までです.つまりこの間が本当の実行文が書いて有る領域であることがわかります。mainのあとの()はしばし忘れて,おまじないとしましょう.また全ての実行文の最後にはセミコロン;をつけて文がここで終わりであることをコンパイラーに教えます.整数型変数であることは,int 変数名; ここでは (int me,res;)で、meとres という整数型の変数を定義しています。 同様に,float 変数名; (float her; )で変数herが実数型であることが分かります.Cでは登場するすべての変数をこのように宣言しなければなりません.またプログラム先頭の#include <stdio.h>はCの関数であるprintf()が置かれている場所がstdio.hであることを示します.printf()は画面に()内のことを表示させる関数です。" result of you and her is = %d \n",res で、double-quataion"の間の形式で画面に出力します。ですから画面に result of you and her is = と表示されます。変数はresを表示するのに%dを使います。%は変数を表示することを示し、dは整数型(decimalのd)です。ちなみに実数型のときは%f (floatの f)としましょう。
さてつぎの例を見て下さい.
---------------------------------------------プログラム例2
#include <stdio.h>
main()
{
int k,sum;
sum = 0;
for (k=0;k<10;k++)
{
sum=sum+k*k ;
printf(" %d %d \n",k,sum);
}
}
---------------------------------------------
ここでは整数型変数sumがkの2乗の和になっている事が読みとれますか?.ただし,初期値 sumに0が代入されています.これを抜かして走らせてみて下さい。ひょっとするととんでもない結果を得て、「計算機がくるってる!」と叫ぶかもしれませんが、それは皆さんのミスです。計算機は自動的に変数の定義をすればゼロをいれてくれません。ここでループ(繰り替えし)はfor(){から}の間で実行されます.まずk=0の場合の計算が実行されます。sumはゼロのままです。次に k++ で k=k+1 が実行され k=1 でsumが1になります.このとき,kの最大値は10をこえない(よって9で終わる)限り計算が実行されます.k=10となると,sumは増えることなく,終了します.つまり } へ飛びます。
こうして2乗和を計算できます.皆さんは初期値が0でない場合や,終了が100でない場合,あるいはもっと進んで実数xの2乗和をつくプログラムを書くことができます.
これを用いてつぎの問題を考えてみましょう.ある年のある場所の例えば虫の固体数Njとして,つぎの年の固体数Nj+1は最も簡単な仮定として,前年の固体数に比例する.すなわち, Nj+1= cNj,
しかし固体数のモデルとしては明らかにこれでは荒すぎます.環境の為に制限が存在し(例えば餌がなくなる),固体数はあまり増えなくなる.すなわり限界Nmaxに近づくと増加は抑制されるとしたほうが,現実的でしょう.そこで,このモデルを,
Nj+1=cNj(Nmax-Nj) と書き換えます.この両辺をNmaxで割って,xj=Nj/Nmaxとすると,xj+1=axj(1-xj), a=cNmax,
として,つぎのプログラムを見て下さい.
--------------------------------------------プログラム例3
#include <stdio.h>
main()
{
int n,nmax;
float x,a;
nmax= 100 ;
printf(" input initial value a : ");
scanf("%f",&a);
printf(" inputs are %d %f %f \n",nmax,a,x);
printf(" n: x \n");
x=0.1;
for(n=0;n<nmax;n++)
{
x= a*x*(1.0-x) ;
printf(" %3d: %lf \n",n,x);
}
}
------------------------------------------------
ここで,scanfはstdioにあるCの関数で,キーボードからのプログラムへのデータ入力を行います.この場合aを入力させています.
この結果がaに依存して収束の様子が違ってくることを確かめて下さい.つまりいろいろのaの場合を試し、年毎の個体数の変動が収束する場合と、振動するばあいが有ることを確かめて下さい。
aがおおよそ3より大きくなると,xは収束せず振動します.我々の数理モデル(漸化式)Nj+1=cNj(Nmax-Nj)は相当簡単なものだったのですが、結果は非常に複雑なふるまいをすることが見て取れますね。自然界で複雑な振る舞いを発見しても、それは必ずしも複雑な機構を反映するとは限りません、という訳でしょうか?
この回の宿題
プログラム例2でS=(1/1+1/2+1/3+1/4+...........+1/x)を計算するプログラムを作りx=23の結果を計算する。
次にプログラム例3で収束の境目となるaの値を可能な限りの精度で求める。
====================付録=====================================
この付録では、計算機の「計算」で要注意事項を学んでもらいます。
それは計算機は万能ではありません。特に「計算」に関して。
次のプログラムを見て下さい。
--------------------------
#include<stdio.h>
main()
{
int n;
float x,z;
double y;
x = y = 0.0;
z = 100000.0;
for(n=0;n<10000;n++)
{
x += z;
y += z;
printf(" float : %f ",x / z );
printf(" double: %lf\n ",y / z );
}
}
------------------------------
このプログラムでは、実数で単精度(float)のxと実数で倍精度(double)のyが、z=10万という単精度の実数を複数回足しあげられています。最終的に印刷printfするときはこれをzで割っていますから、答えは足しあげた回数になるはず(実数を実数で割った実数としています)ですが、、、、、、
実際これを実行すると、5000回ぐらいで妙な事が起こります。自分で確かめてください。理由は単精度の計算と倍精度の計算で桁落ちと呼ばれる現象が起こっているためにこんな事が見えてしまいます。こんな簡単な例でもわかるように、一言で計算すると言っても、計算機の能力や特徴をよく理解したプログラムを組まないと、結果は信用できないものに成りかねません。また皆さんはよくわかった例で計算が正しいことを確かめたうえで、とても手計算ではできないことを計算器にやらせる事がはじめてできることを理解しておいて下さい。
===================付録おしまい==========================