2015 年度「計算数学」 2015-10-23

§4.1 double

(4.1.1) 初めに, 端末の「編集」「プロファイルの設定」「スクロール」で,512 行を 1024 行にしておこう。

(4.1.2) C言語には小数点以下のある数を扱える型がいくつかある。 この授業では double 型のみを紹介する。

(4.1.3)

#include <stdio.h>

main() {
    double x;

    scanf("%lf", &x);
    printf("%f\n", x);
}

double 型の入出力の際には上のように書く。 %lf(パーセント,エル,エフ)と %f の違いに注意せよ。 出力は小数点以下 6 桁となる。 15 桁ぐらいの大きな数や, 0.00000001 のような小さな数を入力してみよ。

    printf("%15.8f\n", x);

とすると「全体で 15 桁,小数点以下 8 桁」で表示される。

    printf("%15f\n", x);

なら「全体で 15 桁」。

    printf("%.8f\n", x);

なら「小数点以下 8 桁」。

(4.1.4) double 型は二進で数値を保存しており, 十進に変換して出力される。 十進の 0.1 は二進では 1/1010 なので循環小数となり, 十進の 1.333 のような近似値として扱われる。 小数点以下 200 桁まで表示してみよ。

(4.1.5) (注意)二進の有限小数は十進でも有限小数である。

(4.1.6) double 型には, 十進で言えば 1.234567×1089 のような形で値が格納されているので, 桁数が大きい整数も代入できる。 しかし,近似値になってしまうこともある。

(4.1.7) 以下のプログラムを動かしてみよ。 (諸数値はここの端末を最大化して使うことを想定して設定してある。)

#include <stdio.h>

main() {
    int n;
    double x;

    x = 1;
    for (n = 0; n < 205; n++) {
        printf("%f\n", x);
        x = x * 10;
    }
}

(4.1.8)

#include <stdio.h>

main() {
    int n;
    double x;

    x = 1;
    for (n = 0; n < 211; n++) {
        printf("%.210f\n", x);
        x = x / 10;
    }
}

(4.1.9)

#include <stdio.h>

main() {
    int n;
    double x;

    x = 1;
    for (n = 0; n < 685; n++) {
        printf("%213f\n", x);
        x = x * 2;
    }
}

(4.1.10)

#include <stdio.h>

main() {
    int n;
    double x;

    x = 1;
    for (n = 0; n < 703; n++) {
        printf("%.211f\n", x);
        x = x / 2;
    }
}

(4.1.11) 10 を 350 回ぐらいかけ合わせると, 「inf」と表示されるようになる。正の無限大といった感じ。 負の無限大なら「-inf」。

(4.1.12)

    printf("%g\n", x);

とすると,1.234567×1089 のように表示される。 (実際の出力がどうなるかは各自で試すこと。)

(4.1.13)

#include <stdio.h>

main() {
    int n;
    double x;

    x = 1;
    for (n = 0; n < 350; n++) {
        printf("%.207g\n", x);
        x = x / 10;
    }
}

どこかから先は 0 になる。

§4.2 double 型を使ったいくつかのプログラム

(4.2.1) 自然対数の底 e の値を,e = 1 + 1/1! + 1/2! + 1/3! + ... として計算する。

#include <stdio.h>

main() {
    int n;
    double x, sum;

    x = 1;
    sum = 1;
    for (n = 1; n <= 25; n++) {
        x = x/n;
        sum = sum + x;
        printf("%2d %.100f\n", n, sum);
    }
    printf("   2.718281828459045235360287471352...\n");
}

(4.2.2) 同様。階乗の計算も行なうバージョン。

#include <stdio.h>

main() {
    int n;
    double factorial, sum;

    factorial = 1;
    sum = 1;
    for (n = 1; n <= 25; n++) {
        factorial = factorial * n;
        sum = sum + 1/factorial;
        printf("%2d %33f %.100f\n", n, factorial, sum);
    }
}

(4.2.3) 階乗を計算するプログラム。

#include <stdio.h>

main() {
    int n;
    double factorial;

    factorial = 1;
    for (n = 1; n <= 200; n++) {
        factorial = factorial * n;
        printf("%2d %f\n", n, factorial);
    }

}

(4.2.4) int 型と double 型を混ぜて使う際, たいていは常識が通用する。 int 型を double 型に代入する際,(たぶん)そのまま格納される。 double 型を int 型に代入すると,(確か)小数点以下が切り捨てられる。

やや間違えやすいケースをプログラムで示す。

#include <stdio.h>

main() {
    double x;

    x = 1/3;
    printf("%f\n", x);

    x = 1.0/3;
    printf("%f\n", x);

    x = 1;
    x = x/3;
    printf("%f\n", x);
}

(4.2.5) 1 + 1/2 + 1/3 + ... を計算するプログラム。

#include <stdio.h>

main() {
    int n;
    double sum, x;

    sum = 0;
    x = 1;
    for (n = 0;    ; n++) {     /* 無限ループ */
        sum = sum + 1/x;
        x++;
        printf("%d: %.200f\n", n+1, sum);
    }
}

発散するはずだが,なかなか大きくならない。

§4.3 数学関数

(4.3.1) 妙な名前に思うかもしれないが, Cコンパイラに備え付けの関数で数学に関連するものを「数学関数」と呼ぶ。 数学関数を使うには #include <math.h> が必要である。 数学関数の一部をあげる。

(4.3.2) x, ydouble 型, 返り値はすべて double 型である。

(4.3.3) 練習問題:二次方程式を解くプログラムを書け。


岩瀬順一