プログラミングプロジェクト＃ 1
久野 靖 (電気通信大学)

2018.8.26

はじめに1

今回は初回ですが、次のことが目標となります。

• プログラムとは何であるか理解し、簡単な Ruby のプログラムを動かせるようになる。
• コンピュータによる実数計算に誤差があることを理解する。

2

プログラムとモデル化

2.1

モデル化とコンピュータ

モデル (model) とは、何らかの扱いたい対象があって、その対象全体をそのまま扱うのが難しい場合に、その特定の側面 (扱いたい側面) だけを取り出したものを言います。
たとえば、プラモデルであれば飛行機や自動車などの「大きさ」「重さ」「機能」などは捨てて「形」「色」だけを取り出したもの、と言えます。ファッションモデルであれば、さまざまな人が服を着る、その「様々さ」を捨てて特定の場面で服を見せる、という仕事だと言えます。
コンピュータで計算をするのに、なぜモデルの話をしているのでしょう? それは、コンピュータによる計算自体がある意味で「モデル」だからです。たとえば、「三角形の面積を求める」という計算を考えてみましょう。底辺が 10cm、高さが 8cm であれば10 × 8= 40(cm2 )2ですし、底辺が 6cm、高さが 5cm であれば6×5= 15(cm2 )2です。「電卓」で計算するのなら、実際にこれらを計算するようにキーを叩けばよいわけです。
１０×８

÷

２＝

しかし、コンピュータでの計算はこれとは違っています。なぜなら、コンピュータは非常に高速に計算するためのものなので、いちいち人間が「計算ボタン」を押していたら人間の速度でしか計算が進まず意味がないからです。
そこで、「どういうふうに計算をするか」という手順 (procedure) を予め用意しておき、実際に計算するときはデータ (data) を与えてそれからその手順を実行させるとあっという間に計算ができる、というふうにします。そしてこの手順がプログラム (program) です。
たとえば面積の計算だったら、手順は☆

×◇÷

２＝1

みたいに書いてあり、あとで「☆は 10、◇は 8」というデータを与えて一気に計算します (もちろん、「☆は 6、◇は 5」とすれば別の三角形の計算ができます)。これを捉え直すと、「個々の三角形の面積の計算」から「具体的なデータ」を取り除いた「計算のモデル」が手順だ、ということになります。1
コンピュータでの計算はモデル、と言うのには別の意味もあります。三角形は 3 つの直線 (正確に言えば線分) から成りますが、世の中には完璧な直線など存在しませんし、まして鉛筆で紙の上に引いた線は明らかに「幅」を持っていて縁はギザギザ曲がっています。また、10cm とか 8cm とか「きっかり」の長さも世の中には存在しません。でも、そういう細かいことは捨てて「理想的な三角形」に抽象化してその面積を考えて計算しているわけです。
逆に言えば、コンピュータでの計算は常に、現実世界をそのまま扱うのではなく、必要な部分をモデルとして取り出し、それを計算している、ということです。この意味での抽象化やモデル化には、皆様はこれまで数学を通して多く接してきたと思いますが、これからはコンピュータでプログラムを扱う時にもこのようなモデル化を多く扱っていきます。

2.2

アルゴリズムとその記述方法「三角形の面積の計算方法」のような、計算 (や情報の加工) の手順のことをアルゴリズム (algorithm)と言います。ある手順がアルゴリズムであるためには、次の条件を満たす必要があります。

• 有限の記述でできている。
• 手順の各段階に曖昧さがない。
• 手順を実行すると常に停止して求める答えを出す。 2
1 番目は、「無限に長い」記述は書くこともコンピュータに読み込ませることも不可能だからです。
2 番目は、曖昧さがあるとそれをコンピュータで実行させられないからです。 3 番目はどうでしょうか。実際にコンピュータのプログラムを書いてみると、手順に問題があって実行が止まらなくなることも頻繁に経験しますが、そのようなものはアルゴリズムとは言えないのです。 3
アルゴリズムを考えたり検討するためには、それを何らかの方法で記述する必要があります。その記述方法には色々なものがありますが、ここでは手順や枝分かれ等をステップに分けて日本語で記述する、擬似コード (pseudocode) と呼ばれる方法を使います。コード (code) とは「プログラムの断片」という意味で、「擬似」というのはプログラミング言語ではなく日本語を使うから、ということです。
三角形の面積計算のアルゴリズムを擬似コードで書いてみます。 4• triarea: 底辺 w、高さ h の三角形の面積を返す•s ← w×h2 。
•面積 s を返す

2.3

変数と代入/手続き型計算モデル

上のアルゴリズム中で次のところをもう少しよく考えてみましょう。

• s ← w×h2 。

モデルを作る時の「不要な側面を捨てる」という作業を抽象化 (abstraction) と言います。つまり、具体的な計算を抽象化したものが手順、という言い方をしてもよいわけです。
2
実は、計算の理論の中に「答えを出すかどうか分からないが、出したときはその答えが正しい」という手順を扱う部分もありますが、ここでは扱いません。
3
停止することを条件にしておかないと、アルゴリズムの正しさについて論じることが難しくなります。たとえば、「このプログラムは永遠に計算を続けるかもしれませんが、停止したときは億万長者になる方法を出力してくれます」と言われて、それを実行していつまでも止まらない (ように思える) とき、上の記述が正しいかどうか確かめようがありません。
4以下ではこのように、何を受け取って何を行う手順 (アルゴリズム) かを明示するようにします。上の例で「返す」というのは、底辺と高さを渡されて計算を開始し、求まった結果 (面積) を渡されたところに答えとして引き渡す、というふうに考えてください。
12

この「←」は代入 (assignment) を表します。代入とは、右辺の式 (expression) 5 で表された値を計算し、その結果を左辺に書かれている変数 (variable — コンピュータ内部の記憶場所を表すもの) に「格納する」「しまう」ことを言います。つまり、「w と h を掛けて、2 で割って、結果を s のところに書き込む」という「動作」を表していて、数式のような定性的な記述とは別物なのです。
2s
数式であれば s = w×h
2 ならば h = w のように変形できるわけですが、アルゴリズムの場合は式は「この順番で計算する」というだけの意味、代入は「結果をここに書き込む」というだけの意味ですから、そのような変形はできないので注意してください (困ったことに、多くのプログラミング言語
では代入を表すのに文字「=」を使うので、普通の数式であるかのような混乱を招きやすいのです)。
モデルという立場からとらえると、式は「コンピュータ内の演算回路による演算」を抽象化したもの、変数は「コンピュータ内部の主記憶ないしメモリ (memory) 上のデータ格納場所」を抽象化したもの、そして代入は「格納場所へのデータの格納動作」を抽象化したもの、と考えることができます。
このような、式による演算とその結果の変数への代入によって計算が進んでいく計算のモデルを手続き型計算モデルと呼び、そのようなモデルに基づくプログラミング言語を命令型言語 (imperativelanguage) ないし手続き型言語 (procedural language) と呼びます。手続き型計算モデルは、今日のコンピュータとその動作をそのまま素直に抽象化したものになっています。このため手続き型計算モデルは、最も古くからある計算モデルでもあるのです。
コンピュータによる計算を表すモデルとしては他に、関数とその評価に土台を置く関数型モデルや、論理に土台を置く論理型モデルなどもあるのですが、上記のような理由から、手続き型モデルが今のところもっとも広く使われています。

3

アルゴリズムとプログラミング言語

3.1

プログラミング言語

プログラムとは、アルゴリズムを実際にコンピュータに与えられる形で表現したものであり、その具体的な「書き表し方」ないし「規則」のことをプログラミング言語 (programming language) と呼びます。これはちょうど、人間が会話をする時の「話し方」として日本語、英語など多くの言語があるのと同様です。ただし、自然言語 (natural language — 日本語や英語など、人間どうしが会話したり文章を書くのに使う言語) とは違い、プログラミング言語はあくまでもコンピュータに読み込ませて処理するための人工言語であり、書き方も杓子定規です。
ひとくちにプログラミング言語といっても、実際にはさまざまな特徴を持つ多くのものが使われています。ここでは、プログラムが簡潔に書けて簡単に試して見られるという特徴を持つ、Ruby という言語を用いてゆきます。

3.2

Ruby 言語による記述

では、三角形の面積計算アルゴリズムを Ruby プログラムに直してみましょう。本クラスでは入力と出力は基本的に irb コマンド 6 の機能を使わせてもらって楽をするので、計算部分だけを Ruby のメソッド (method) 7 として書くことにします。先にアルゴリズムを示した、三角形の面積計算を行うメソッドは次のようになります。

def triarea(w, h)s = (w * h) / 2.0
return send
詳細を説明しましょう。
プログラミングで言う式とは、計算のしかたを数式に似た形で記述したものを言います。先に説明した、電卓で計算する手順を記したようなものと思ってください。
6
Ruby の実行系に備わっているコマンドの 1 つで、さまざまな値をキーボードから入力し、それを用いてプログラムを動かす機能を提供してくれます。
7
メソッドは他の言語での手続き・サブルーチン (subroutine) に相当し、一連の処理に名前をつけたもののことです。
5

3

1. 「def メソッド名」〜「end」の範囲が 1 つのメソッド定義になる。
2. メソッド名の後に丸かっこで囲んだ名前の並びがあれば、それらはパラメタ (parameter) ない
し引数 8 の名前となる。メソッドを呼び出す時、各パラメタに対応する値を指定する。
3. メソッド内には文 (statement — プログラムの中の個々の命令のこと) を任意個並べられる。各々の文は行を分けて書くが、1 行に書く場合は「;」で区切る。たとえば上の例のメソッド本体を1 行に書きたければ「s = (w * h) / 2.0; return s」とする。
4. 文は原則として先頭から順に 1 つずつ実行される。
5. return 文「return 式」を実行するとメソッド実行は終了 (式の値がメソッドの結果となる)。
上の例は擬似コードに会わせるように、面積の計算結果を変数 s に入れてからそれを return していましたが、return の後ろに計算式を直接書くこともできるので、次のようにしても同じです。

def triarea(w, h)return (w * h) / 2.0end
このように、たったこれだけのコードでも、大変細かい規則に従って書き方が決まっていることが分かります。要は、プログラミング言語というのはコンピュータに対して実際にアルゴリズムを実行する際のありとあらゆる細かい所まで指示できるように決めた形式なのです。
そのため、プログラムのどこか少しでも変更すると、コンピュータの動作もそれに相応して変わるか、(もっとよくある場合として) そういうふうには変えられないよ、と怒られることになります。
いくら怒られても偉いのは人間であってコンピュータではないので、そういうものだと思って許してやってください。

3.3

動かしてみよう!

ではプログラムを動かしてみます。まず、テキストエディタ (メモ帳など) で上と同じ内容を sample1.rbというファイルに打ち込んで保存してください。この、人間が打ち込んだプログラムを (プログラムを動かす「源」という意味で) ソースないしソースコード (source code) と呼びます。Ruby のソースファイルは最後を「.rb」にするのが通例です。そして、先に進む前に ls を使って、作成したファイルがあることを確認してください。ディレクトリが違っている場合はソースファイルのあるディレクトリに移動しておくこと。
いよいよ、このコードを動かしてみましょう。前述のように、この講義では irb というコマンドを通じて Ruby プログラムをファイルから読み込んだり実行解しさせます。 irb の動かし方はシステムによって違うので担当教員に教わってください。以下の例ではまず irb を起動するところから示しています (「%」はプロンプト文字列のつもりなので打ち込まないでください)。

% irbirb(main):001:0>
この「irb なんとか>」というのは irb のプロンプト (prompt — 入力をどうぞ、という意味の表示)で、ここの状態で Ruby のコードを打ち込めます。
プロンプトの読み方を説明すると、 main というのは現在打ち込んでいる状態がメインプログラム(最初に実行される部分) に相当することを意味しています。次の数字は何行目の入力かを表しています。最後の数字はプログラムの入れ子 (nesting — 「はじめ」と「おわり」で囲む構造の部分) の中に入るごとに 1 ずつ増え、出ると 1 ずつ減ります。とりあえずあまり気にしなくてよいでしょう。以後の実行例では見た目がごちゃごちゃしないように「irb>」だけを示すことにします。

8

メソッドを使用するごとに、毎回異なる値を引き渡して、それに基づいて処理を行わせるための仕組みです。

4

次に load(ファイルからプログラムを読み込んでくる、という意味です) で sample1.rb を読み込ませます。ファイル名は文字列 (string) として渡すので’’ または""で囲んでください。 9irb> load ’sample1.rb’=> true
irb>
true が表示されたら読み込みは成功で、ファイルに書かれているメソッド triarea が使える状態になります。成功しなかった場合は、ファイルの置き場所やファイル名の間違い、ファイル内容の打ち間違いが原因と思われるので、よく調べて再度 load をやり直してください。
なぜわざわざ 3〜4 行程度の内容を別のファイルに入れて面倒なことをしているのでしょうか? それは、メソッド定義の中に間違いがあった時、定義を毎回 irb に向かって打ち直すのでは大変すぎるからです。このため、以下でもメソッド定義はファイルに入れて必要に応じて直し、 irb では loadとメソッドを呼び出して実行させるところだけを行う、という分担にします。
load が成功したら triarea が使えるはずなので、それを実行します。
irb> triarea 8, 5=> 20.0
irb> triarea 7, 3=> 10.5
irb>
確かに実行できているようです。 irb は quit で終わらせられます。

irb> quit%
苦労の割に大した結果ではない感じですが、初心者の第 1 歩として、着実に進んでいきましょう。
演習 1 例題の三角形の面積計算メソッドをそのまま打ち込み、irb で実行させてみよ。数字でないものを与えたりするとどうなるかも試せ。
演習 2 三角形の面積計算で、割る数の指定を「2.0」でなくただの「2」にした場合に何か違いがあるか試せ。
演習 3 次のような計算をするメソッドを作って動かせ。 10a. 2 つの実数を与え、その和を返す (ついでに、差、商、積も)。何か気づいたことがあれば述べよ。
b. 「%」という演算子は剰余 (reminder) を求める演算である。上と同様に剰余もやってみよ。
何か気づいたことがあれば述べよ。
c. 円錐の底面の半径と高さを与え、体積を返す。11d. 実数 x を与え、x の平方根を出力する。さまざまな値について計算し、小数点以下何桁くらい表示されるか (計算の精度がどれくらいあるか) 検討せよ。12e. その他、自分が面白いと思う計算を行うメソッドを作って動かせ。
9
本来ならメソッドに渡すパラメタは丸かっこで囲むのですが、Ruby では曖昧さが生じない範囲でパラメタを囲む丸かっこを省略できます。本資料ではプログラム例の丸かっこは省略しませんが、 irb コマンドに打ち込む時は見た目がすっきりするので丸かっこを適宜省略します。
10
1 つのファイルにメソッド定義 (def ... end) はいくつ入れても構わないので、ファイルが長くなりすぎない範囲でまとめて入れておいた方が扱いやすいと思います。
11
円錐の体積は「底面積×高さ× 31 」。底面積は「2πr 2 」。
12x の平方根 (square root) は Math.sqrt(x) で計算できます。または x の 0.5 乗 (x ** 0.5) としても計算できます。

5

本日の課題 1A「演習 3」で動かしたプログラム (どれか 1 つでよい) を含むレポートを提出しなさい。プログラムと、簡単な説明が含まれること。アンケートの回答もおこなうこと。

Q1. プログラム、って恐そうですか? 第 2 外国語と比べてどう?
Q2. Ruby 言語のプログラムを打ち込んで実行してみて、どのような感想を持ちましたか?
Q3. 本日の全体的な感想と今後の要望をお書きください。

次回までの課題 1B「演習 3」の小課題全体から 2 つ選択してプログラムを作り (ただし 1A で提出したものは除外、以後も同様)、レポートを提出しなさい。プログラムと、課題に対する報告・考察 (やってみた結果・そこから分かったことの記述) が含まれること。アンケートの回答もおこなうこと。

Q1. プログラムを作るという課題はどれくらい大変でしたか?
Q2. 実際に複数のプログラムを打ち込んで動かしてみて、想像していたのと違うところはありましたか。
Q3. 課題に対する感想と今後の要望をお書きください。

6