2014 Data Structures and Algorithms



#include <stdio.h>
#include <stdlib.h>
 
void RoundError() {
    float f1, f2;
    f1 = 0.1f;
    f2 = 0.100000001f;
 
    /* f1,f2をそれぞれ20 桁(小数点以下18 桁)ぶん表示 */
    printf("%20.18f \n%20.18f \n", f1, f2);
}
 
int main(void) {
    RoundError();
    return 0;
}




#include <stdio.h>
#include <stdlib.h>
 
void RoundError2() {
    double d1, d2;
    d1 = 0.1;
    d2 = 0.100000001;
 
    /* d1,d2をそれぞれ20 桁(小数点以下18 桁)ぶん表示 */
    printf("%20.18lf \n%20.18lf \n", d1, d2);
}
 
int main(void) {
    RoundError2();
    return 0;
}



コードを次のように変更してみよう。
  1. floatをdoubleに変えて、f1とf2に代入する値の最後にある"f"を削除してから、動かしてみよう。
#include <stdio.h>
#include <stdlib.h>
 
void CancellationError()
{
    float f1, f2;
    f1 = 1.0000101f;
    f2 = 1.0000100f;
 
    /* 「f1-f2」「f1+f2」をそれぞれ表示 */
    printf("%15.13f-%15.13f=%15.13f \n", f1, f2, f1 - f2);
    printf("%15.13f+%15.13f=%15.13f \n", f1, f2, f1 + f2);
}
 
int main(void) {
    CancellationError();
    return 0;
}



コードを次のように変更してみよう。
  1. floatをdoubleに変えて、f1とf2に代入する値の最後にある"f"を削除してから、動かしてみよう。
  2. さらに、100万回加えるところを、1億回加えるように変えてみよう。
#include <stdio.h>
#include <stdlib.h>
 
void LossOfTrailingDigit() {
    unsigned int n;
    float f1, f2;
    f1 = 1000000.0f;      /* 100万 */
    f2 = 0.000001f;       /* 100万分の1 */
 
    /* f1にf2を100万回加える */
    for(n = 0; n < 1000000; n++) {
        f1 += f2;
    }
 
    /* 「1000001」が出力されるはず……? */
    printf("%f \n",f1);
}
 
int main(void) {
    LossOfTrailingDigit();
    return 0;
}



コードを次のように変更してみよう。
  1. 解析したい関数を、自分で解が分かっている2次方程式に変えてみよう。
  2. 解析したい関数を、自分で解が分かっている3次方程式に変えてみよう。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
 
/* 解析したい関数 */
double func(double x) {
    return x * x * x * x * x
        - 10.0 * x * x * x * x
        + 25.0 * x * x * x
        + 40.0 * x * x
        + 200.0 * x - 500.0;
}
 
/* 2分探索法(バイナリサーチ) */
double BinarySearch(void) {
    double left, mid, right, epsilon;
 
    /* ↓「答に非常に近い」という範囲を定義する。 */
    /* この値をいろいろと変えることで,答の精度を調節できる。 */
    /* ちなみに,あまり小さくしすぎると情報落ちの関係で */
    /* 答が求まらなくなってしまうので注意。 */
    epsilon=0.00001;
 
    /* 「leftとrightの間に確実に解がある」という範囲を指定する */
    left = 1.0;
    right = 3.0;
 
    /* 範囲をひたすら絞り込む */
    while(fabs(right - left) > epsilon && fabs(func(left)) > epsilon) {
        mid = (left + right) / 2.0;
 
        /* func(left)とfunc(mid)が同符号なら */
        if(func(left) * func(mid) >= 0.0) {
            left = mid;           /* leftの位置をmidに合わせる */
        } else {
            right = mid;          /* rightの位置をmidに合わせる */
        }
    }
    return left;
}
 
int main(void) {
    double d;
    d = BinarySearch();
    printf("方程式の解は%lf,"
            "そのときのfunc(x)は%lfです。\n", d, func(d));
    return EXIT_SUCCESS;
}