課題(6月27日締切分)について

(2e-10+2e+10)-2e+102e-10+(2e+10-2e+10)の二つの実数の計算でした。 数学的には、二つの計算結果は等しくなるはずですが、 計算結果は等しくならなかったはずです。

計算機内部では、

displaymath145

という表現方法が用いられています。gif nを仮数部とよび、mを指数部と呼びます。もちろん、それぞれは有限です。 従って、Pascalの実数のもつ精度も有限です。そのために 小さな実数2e-10と、それと比較して圧倒的に 大きな実数2e+10とを足し算してしまうと、 結局、2e+10になってしまいます。gif このような理由により、 2e-10+(2e+10-2e+10)が、2e-10になるのに対して、 (2e-10+2e+10)-2e+10は、0.0になってしまいます。

Pascalという言語に限らず、計算機の上での実数計算はどうしても誤差が入っ てきてしまいます。計算機上での実数計算をするときには誤差のことを常に気 にとめましょう。

代入文

以前、変数は「データを格納する箱」と説明しました。代入文は、変数という 「箱」には式の計算結果を格納するという操作を意味します。

変数名 := 式
この文が実行されると、左辺の変数に、右辺の式の計算結果の値が格納されま す。左辺の変数の型と右辺の式の型は同一でなければなりません。

例えば、nという整数型の変数があったときに代入文

n := 1
が実行されると、変数nには整数値1が格納されます。

n := n + 1
が実行されると、式n + 1の計算結果の値が変数nに格納されます。 すなわち、変数nという「箱」の中身の整数値が1だけ増やされる わけです。

Pascalの式と演算子(その1)

Pascalの文法事柄の中で、式と文は非常に重要な概念です。は「〜を 実行せよ!」という計算機に対する命令です。その実行結果は変数の値の変化 や(画面などの)入出力装置の状態の変化gifとして得ることができます.一方、 については式の値(value)が計算結果となります。 gif

次に、式がどのように組みあげられていくかという文法的な側面について見て いきましょう。

式は演算子により結合されることにより更に大きな式を構成します。たとえば、 (1+2)*3では次のようになります:

12が式であり、それが、+という演算子により、 1+2という式が構成されます。そして更にこの式と3が、*という 演算子により、(1+2)*3という式を構成しているわけです。

式は、変数や定数を基にして、演算子や関数を使って組みあげられていくわけ です。ここではとりあえず演算子にしぼって解説していきましょう。

式と式を演算子で自由自在に何らの制限なく結合できるわけではありません。 演算子が結ぶことができる式には、それが表現する型(データの種類)により制 限があります。ある演算子は、整数型の式だけを結合することができたり、ま た別の演算子は、実数型の式だけしか結合できなかったりします。この点に注 意して、以下で紹介する演算子の説明を読んでください。

算術演算子

算術演算子(arithmetic operator)には次のようなものがあります。

*、整数商div、余りmod、和+、符号の維持(プラ ス)+、差-、符号の反転(マイナス)-

気をつけなければならないのは、結ばれる式の型(データの種類)です。

以下の演算子は、被演算子(結ばれる式)の型が両方が整数のときは、結果型 (結ばれてできる式の型)は整数型です。

tabular57

次の2つも前の3つと同じですが、前の3つは実数型の被演算子を取りうる(後述) のに対して、次の2つは被演算子は整数型のものしか許されません。

tabular42

次の4つの被演算子は、実数型である被演算子(演算子で結ばれる式)をとるも のです。最初の3つは、2つある被演算子のうち1つ以上が実数型であるときに、 結果の型が実数になります。両方とも整数型のときには、前述のとおり結果型 は整数型になってしまうことに注意してください。

tabular68

(上の説明に納得できないひとのための)練習

1 + 1という式の計算結果と1 + 1.0という式の計算結果を表示 するプログラムを実行して結果を比べてみましょう。

あと、関係演算子論理演算子という演算子があります。これは、 if文を紹介したあとで、説明しましょう。

if文

次に示すプログラムは整数の和差積商と剰余を計算するものです。

program arithmetic(input,output);
var i, j : integer;
begin
    read(i,j);
    writeln('i = ', i);
    writeln('j = ', j);
    writeln('i + j = ', i + j);
    writeln('i - j = ', i - j);
    writeln('i * j = ', i * j);
    writeln('i div j = ', i div j);
    writeln('i mod j = ', i mod j)
end.

次に実行例(2と3との計算例)を示します。

sino% pc arithmetic
sino% ./arithmetic
2 3      (←これが入力された2つの整数)
i =          2
j =          3
i + j =          5
i - j =         -1
i * j =          6
i div j =          0
i mod j =          2
sino%

次に、2と0とを与えて実行すると次のようになります。

sino% ./arithmetic
2 0
i =          2
j =          0
i + j =          2
i - j =          2
i * j =          0
i div j = libm-290 : UNRECOVERABLE (訳:復旧不能)
  Scalar integer value divided by a scalar integer zero.
(訳:整数値が整数0により割り算されてしまいました)
Abort (core dumped)
sino%

``Abort''というのは日本語訳は「失敗」ですが、Unixでのエラーの種類の一 種で、異常終了の場合に起るものです。gif 数学では、0による割り 算は未定義ですが、Pascalではエラーが発生してプログラムが異常終了してし まいます。

このようなことが発生しないようにするためには、二番目の整数が0ではない かあらかじめチェックしておくことが必要になります。ここでは、そのような ときには割り算は計算せずに警告文を表示するようにプログラムを変更するこ ととします。

program arithmetic(input,output);
var i, j : integer;
begin
    read(i,j);
    writeln('i = ', i);
    writeln('j = ', j);
    writeln('i + j = ', i + j);
    writeln('i - j = ', i - j);
    writeln('i * j = ', i * j);
    if j = 0 then 
        writeln('The 2nd input should be non-zero.')
    else 
    begin
        writeln('i div j = ', i div j);
        writeln('i mod j = ', i mod j)
    end
end.

ここでは、整数型変数jの値が0でないかどうかチェックをするために、 if文というものを利用しています。

if文は、

    if 論理型の式 then 文1 else 文2
という形をしていてます。「論理型の式」は、計算すると論理値(true もしくはfalse)というものが結果の値となるような式です。

j = 0は、変数jが整数0と等しいときにtrueという 値が計算結果になり、そうでないときfalseという計算結果になります。 イコール=関係演算子とよばれるものの一種です。

if文の意味は、「論理型の式」の計算結果がtrueのとき「文1」が実行 され、そうでないとき、「文2」が実行される、というものです。

従って、プログラム例のような

    if j = 0 then 文1 else 文2
というif文では、変数jの値が0に等しいときには、文1が実行されて、 等しくないときには、文2が実行されるのです。

このプログラムでは、「文1」でなすべき作業は警告文を表示するという作業 だけですから、writeln文一つですむわけですが、「文2」では商の表 示をするwriteln文と余りの表示をするwriteln文の二つの文を実 行する必要があります。このようなときに用いられるのが複合文です。gif

複合文は、

begin 文1 ; 
      文2 ;  
      … 
      文n 
end.
というふうに、1つ以上の文をセミコロンで区切ったものをbegin endで囲んだものです。1つのときは単にbeginendで囲むだけ です。複合文の意味は、並んだ文を前から順に実行するというものです。

従って、

    begin
        writeln('i div j = ', i div j);
        writeln('i mod j = ', i mod j)
    end
という二つのwriteln文から構成される(一つの)複合文は商を表示した あと、剰余を表示するわけです。

関係演算子

=というように二つの式の値を比較する演算子として関係演算子 というものが用意されています。

tabular88

被演算子(値が比較される式)の型には、整数型や実数型の他、論理型や文字型、 文字列型なども許されれます。被演算子のうち一つが実数型で、もう一つが整 数型の場合には、整数型の被演算子が実数に変換された後に比較されます。

2次方程式の解法

次に示すプログラムは、二次方程式

displaymath153

の係数a,b,c( tex2html_wrap_inline163 )を実数値の入力として読みこんで、 実根が存在するときには2つの実根を出力するプログラムです。

2次方程式の根の公式によると判別式を

displaymath154

とおくと、二つの根は、 tex2html_wrap_inline165 ならば tex2html_wrap_inline167
D < 0ならば tex2html_wrap_inline171

でした。これに素直に従ってプログラムを作成すると、

program eq1(input,output);
var a, b, c, d, sd, x1, x2 : real;
begin
    read(a,b,c);
    if a = 0 then 
        writeln('a should be non-zero')
    else
    begin
        d := b*b - 4*a*c;
        if d >= 0 then
        begin
            sd := sqrt(d);
            x2 := (-b - sd)/(2*a);
            x1 := (-b + sd)/(2*a);
            writeln(x1);
            writeln(x2)
        end
        else writeln('Imaginary root')
    end
end.
となります。ちなみに、sqrtは、規定関数(あらかじめ用意されている 関数)であり、sqrt(実数式)で、実数式の平方根(ルート)を意味します。

課題

課題提出方法

プログラムeq1eq2eq3の3つのプログラムとその実行 結果を添えて、レポートを作成してください。実行結果について考察したこと があれば、それについても記しておいてください。

kadai4というSubjectで、7月11日(金)までに電子メールで提出し なさい。

...という表現方法が用いられています。
もう少し厳密にいうと、計算機は二進表現なので、 tex2html_wrap_inline147
...結局、2e+10になってしまいます。
このように大きい実数と小さい実数との足し算で 生じる誤差を情報落ちと呼びます。 また、近い値の実数の引き算から生じる誤差のことを 桁落ちと呼びます。

...や(画面などの)入出力装置の状態の変化
計算機科学用語ではこれを 副作用といいます。副作用というと意図しない悪影響のように思えます が、ここではそのような意味はありません。
...式については式の値(value)が計算結果となります。
ちなみに式から値(value)を得ることを評価 (evaluate)とい います。
...種で、異常終了の場合に起るものです。
``core dumped''はメモリ (古代名:コア)をファイル(ファイル名core)の中に投げ捨てたということです。 この投げすてられたものを利用して、どうしてこんなことになったかその理由 を解析することも可能ですが、初心者のうちは不要です。自分のディレクトリ でcoreファイルを発見したら消しておきましょう。
...行する必要があります。このようなときに用いられるのが複合文です。
前回の資料で説明済みですが、もう一回説明します。
 



Mon Jun 30 11:48:41 JST 1997