Powered by SmartDoc

ソフトウェア概論A/B (2021/10/08)
Ver. 1.0

2021年10月8日
栗野 俊一
kurino@math.cst.nihon-u.ac.jp
http://edu-gw2.math.cst.nihon-u.ac.jp/~kurino/2021/soft/soft.html
ソフトウェア概論 A/B2021年10月8日 の資料

目次

講義資料

当日の OHP 資料

講議中に作成したプログラム

本日の課題

課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。

課題 20211008-01 : 一つ浮動小数点数値をキーボードから入力し、その立方根を出力する

Download : 20211008-01.c

20211008-01.c
/*
 * 20211008-01-QQQQ.c
 *
 *	一つ浮動小数点数値をキーボードから入力し、その立方根を出力する
 *	手段としては、「二分法」を使う
 *
 *	コンパイル :
 *		cc  -c 20211008-01-QQQQ.c
 *		cc -o 20211008-01-QQQQ.exe 20211008-01-QQQQ.o
 *	実行 :
 *		./20211008-01-QQQQ.exe
 *
 */

#include <stdio.h>

/*
 *
 */

#define	EPSILON	0.00000001		/* 誤差幅 */

/*
 * double regula_falsi_cubic_root ( double a, double min, double max )
 *		double a	立方根の元になる数(正を仮定している)
 *		double min, max 根の入る区間の範囲
 *		return		a 立方根
 *			二分法により、a の立方根を求める
 *			0 < min < a の立方根 < max
 */

double regula_falsi_cubic_root ( double a, double min, double max ) {
	double mid;	/* 答えを含む区間の中点 */

	while ( max - min > EPSILON ) {	/* 精度が不十分 */
		mid = (max + min) / 2.0;	/* 区間の中点を求める */

		/* min が解のどちら側にあるかを調べ.. それに併せて区間を調整 */
		/* f(x)=x^3-a */
		if ( mid * mid * mid - a < 0.0 ) {	/* f(mid) の符号を確認 */
			/* 中点は解の左にあった ( min を更新する )  */

	/*
	**	 この部分を完成させなさい
	*/

		} else {
			/* 中点は解の右にあった ( max を更新する ) */
			max = mid;
		}
	}

	/* 区間は十分に狭いので.. 近似値として、区間の中点を答える */

	return (min+max)/2.0;

}

/*
 * double cubic_root ( double a )
 *		double a	立方根の元になる数
 *		return		a 立方根
 *			a の立方根を求めて結果として返すが、
 *			計算の基本は、regula_falsi_cubic_root にまかせる
 *			ここでは、計算の正規化を行う
 */

double cubic_root ( double a ) {

	if ( a < 0.0 ) {					/* a が負の数ならば.. */
		/* -a の立方根を計算し、その結果の負数を返す */
		/*「-a」 は 「(-1.0) * a」 の省略記法 */

	/*
	**	 この部分を完成させなさい
	*/

	} else if ( a < 1.0 ) {				/* a が 1.0 未満なら */

	/*
	**	 この部分を完成させなさい
	*/

										/* 立方根は a と 1.0 の間にある */
	} else {							/* そうでなければ.. */
		return regula_falsi_cubic_root ( a, 1.0, a );
										/* 立方根は 1.0 と a の間にある */
	}

}

/*
 *	main
 */

int main( double argc, char *argv[] )
{
	double d;	/* 入力した、立方根を計算したい数値を納める変数 */
	double r;	/* 立方根の計算結果 */

		   /* 実数値をキーボードから入力する */
	printf ( "実数値を一つ入力してください : " );
	scanf ( "%lf", &d );

		/* 変数 d に入っている実数値の立方根を求めて、変数 r に代入 */

	/*
	**	 この部分を完成させなさい
	*/


	printf ( "%f の立方根は %f です。\n", d, r );
	printf ( "誤差は %f - %f^3 = %f になります。\n", d, r, d - r * r * r );

	return 0;
}
入力例
12.34
20211008-01.c の実行結果
$ ./20211008-01-QQQQ.exe
実数値を一つ入力してください : 12.340000
12.340000 の立方根は 2.310850 です。
誤差は 12.340000 - 2.310850^3 = -0.000000 になります。
$ 

課題 20211008-02 : 関数 sin(x) の区間 [0,π/4] の定積分値

Download : 20211008-02.c

20211008-02.c
/*
 * 20211008-02-QQQQ.c
 *
 *	関数 sin(x) の区間 [0,π/4] の定積
 *
 *	コンパイル :
 *		cc ' -c 20211008-02-QQQQ.c
 *		cc -o 20211008-02-QQQQ.exe 20211008-02-QQQQ.o
 *	実行 :
 *		./20211008-02-QQQQ.exe
 *
 */

#include <stdio.h>
#include <math.h>		/* 数学的関数 sin を利用するので.. */

/*
 * リーマン積分を利用する
 */

#define FRACTIONAL 1000.0 /* 区間の等分数 */

/*
 * f(x)=sin(x)
 */

double f(double x) {

	   /*
		* 引数 x に対して、x の 正弦値 sin(x) を値として返す関数
		*/


	/*
	**	 この部分を完成させなさい
	*/

}

/*
 reman_sum ( double min, double max, double delta )
	S_1 〜 S_{n}^1 の和を計算する
*/

double reman_sum ( double min, double max, double delta ) {
	double sum = 0.0;	/* 総和の計算結果 */
	double x = min;		/* 区分点の x 座標 ( 最初は min の値 ) */

	while ( x < max )	{	/* x の値が区間内ならば.. */
		/* 短冊の面積を計算し、加える */

	/*
	**	 この部分を完成させなさい
	*/

		/* x の座標を次の点に移動させる */
		x = x + delta;
	}

	/* この時点で sum には積分値が入っている */
	return sum;
}

/*
 * リーマン積分
 *
 *   関数の積分値が、小さな幅の短冊の面積の和で近似できる事を利用
 *
 *   solove_reaman ( double min, double max )
 *
 */

double solve_reman ( double min, double max ) {
	/*
       min から max までを積分
       基本は reman_sum に任せる
	*/

    return reman_sum ( min, max, (max-min)/FRACTIONAL );
}

/*
 *	main 関数
 */

int main ( void ) {

	printf ( "関数 f(x)=sin(x) を区間[0,π/4]で数値定積分する。\n" );

	printf ( "リーマンの定義に従って計算した答えは %f になりました。\n",
		solve_reman ( 0.0, M_PI/4.0 )
	);

	printf ( "解析的な計算の結果は 1-√2/2 なので、誤差は %f になり、答えに近い事が分ります\n",
		solve_reman ( 0.0, M_PI/4.0 ) - (1.0-sqrt(2.0)/2.0)
	);

	return 0;
}
20211008-02.c の実行結果
$ ./20211008-02-QQQQ.exe
関数 f(x)=sin(x) を区間[0,π/4]で数値定積分する。
リーマンの定義に従って計算した答えは 0.293171 になりました。
解析的な計算の結果は 1-√2/2 なので、誤差は 0.000278 になり、答えに近い事が分ります
$