フリーソフトの小道   

コンピュータ・プログラマー養成講座(入門編)
   第3回 プログラムの構造化の具体的事例


「素数を順に表示する」プログラムに挑戦

 前回(第2回)では、入力した数値が素数であるかどうかを判定するプログラムの作成の各段階について プログラム構造の作り方を考えてみた。 今回は、前回より大きなプログラム構造を考え、 「プログラムの構造化」の方法と、「構造化によるメリット」について説明してみる。
 前回の素数判定プログラムを使えば、タイトルの「素数を順に表示する」ことは簡単に出来そうなことはだれにでも分かる。 プログラムの構造としては次のようなものが考えられる。

  1. 打ち切りする上限値を入力する。
  2. 打ち切り数が10,000 を超えておれば10,000とする。
  3. スタートする数 J を 2 とする。
  4. 数 J を「素数判定」する。
  5. 素数であれば、素数として表示する。
  6. 数 J を1増やす。
  7. 数 J が上限値未満でれば、処理番号 4 に戻り、処理を継続する。
  8. 数 J が上限値以上であれば、終了する。

 処理1,2 の上限値に関する処理が素数処理を打ち切るためのもので、 無限に続けることはできないからだ(終わりが無い)。 今回は10,000を上限値の最大値としたが、 計算処理中の「ビット落ち」がない、表示可能、時間の制約が無いなどの範囲であれば 数値は自由に設定してよい。
 素数判定の処理4 は前回のものを再利用すればよい。 ただし、この場合では、前回のようなデータの入力チェックは不要である。

 前回と同様に、 Delphi(フリーソフトであるパスカル・コンパイラで Windows のソフト開発ができる。 Borland サイト から無料でダウンロード可能) を利用して作成してみよう。

 前回のプログラムを修正する形で、処理4 の部分のプログラム(サブプログラム、サブルーチンという)を作成する。 まず、前回のプログラムを再掲載し、修正部分を追加、不要な部分を消す作業を行ってみよう。 サブプログラム名として SosuuHantei とし、判定結果をboolean型(真偽型)で返すサブプログラムとする。 入力チェックなど前段階処理、表示部分などが要らなくなるので僅かの部分以外はすべて削除となる。 その結果、素数判定サブプログラムは次のようになる。

function SosuuHantei(n: integer): boolean;
var
  i:integer;
  f:boolean;
begin
  SosuuHantei:=True;
  for i:=2 to n-1 do begin   {その数未満で割り切れるかどうか調べる}
    if n mod i =0 then begin SosuuHantei:=False; break; end;  {割り切れたら素数でない}
  end;
  {割り切れなかったから素数だ}
end;

 次に、プログラムの本体を作る。先ほどのプログラムの構造にしたがって、構成してゆけばよい。 数値2から上限値まで順に素数かどうかを調べればよい。
 ただし、このプログラムを動かす上で注意が必要なことは、 この処理がどのような影響をコンピュータに与えるかに配慮が必要である。 例えば、処理に思わぬ時間が必要な場合だ。無限、または長時間コンピュータが処理することは、 コンピュータが止まっているのと同じであり、避けなければならない。 また、無限にデータを出力し続ける場合も避けなければならない。 また、コンピュータそのものの能力(計算精度)の限界という問題もある。

procedure TForm1.Button1Click(Sender: TObject);
const
  numberstr='0123456789';
var
  s,c: string;
  f: boolean;
  i: integer;
  n: integer;
begin
  s:=Edit1.text;  {限界値入力}
  n:=0; f:=true;
  {上限値入力判定処理(前回と同じ)}
  for i:=1 to length(s) do begin
    c:=copy(s,i,1);
    if('0'>c) or (c>'9') then begin f:=false; break; end;
    n:=n*10+pos(c,numberstr)-1;
  end;
  if n >10000 then n:=10000;
  str(n,s); Edit1.Text:=''; Edit1.Text:=s;
  {素数発見処理}
  SosuuList.Clear;  {表示領域を初期化}
  if f then begin  {上限値の誤りが無ければ処理開始}
    for i:=2 to n do  {2から上限値nまで素数判定}
      if SosuuHantei(i)=True then begin  {素数であれば表示欄に追加する}
      str(i,s);{数を文字列に変換}
      SosuuList.Text:=SosuuList.Text+' '+s;  {表示部に追加する}
    end;
  end;
end;

 このプログラムを動かしてみると、上限値が1000程度であれば、ほぼ瞬時に結果が出る。 しかし、上限値が10000になると素数を全て見つけるのに随分と時間がかかるようになる。 このように、限界値の最適値はプログラムを動かしてみるとおよその値は分かる。 1000,000などを上限値とした場合、このプログラムのままであればいつまで経っても終わらない、 フリーズした状態に陥るのは明らかだ。
 それでは、大きな素数を見つけることは無理なのか? そうではないのだ。このプログラムの 「やりかた」 が悪いからなのだ。 プログラムの処理の 「やりかた」 をアルゴリズムという。 アルゴリズムの改良は飛躍的に処理能力を高める。アルゴリズムの威力は、多くの場合に証明されているのだ。 アルゴリズムの改良がどのように威力を発揮するかをいずれ実例を交えて説明するつもりである。

 実際に動かして見たい人は ダウンロード して使ってみてください。まだまだ改善する部分が残っているが、 このコーナーの趣旨にはないのでこれ以上の手を加えないものとします。  管理人(志)



プログラミングコンテスト 第1回 〜素数を見つけるスピードを競う〜 を開催します!

 素数を見つけるプログラムを募集します。10,000 までの素数を見つけて、 ファイルにテキストファイルとして保存するまでの時間を競うコンテストです。応募者はいるのかな? 言語は自由です。自分の得意なもので参加ください。プログラム処理の時間は自主的に計って報告ください。 応募者を信頼しています。なお、コンテスト上位になった人のソースリストなどを提出して頂くことがありますので その場合には協力ください。
 コンパイラ部門とインタープリタ部門とに分けます(部門の区別がなければコンパイラが圧倒的有利なのは当然だからです)。 通常、同一ソースのプログラムの場合、100倍程度は違ってきます。 また、Windows上でのプログラムはGUIの処理の部分で時間を取られる関係で少し不利だと思います。 高性能なパソコン(ペンティアム4で3GHz級)で、優秀なコンパイラ(C/C++コンパイラのようです)を使えば飛躍的な速度アップが見込めます。 しかし、アルゴリズムの威力が絶大です。プログラマの能力がパソコンを越えるのです。

 プログラムの内容は 「素数を速く見つけ、その数字をファイルに保存する」までの時間を競う。ものです。
 コンパイラ部門とインタープリタ部門を設けます。 応募は、コンテスト 応募規定 にしたがって、「物理の小道」掲示板に書き込んでください。

質問、意見などがありましたら、掲示板、メールなどでお寄せください。




このページは 2003/2/1 に作成されました。