Powered by SmartDoc

ソフトウェア概論A/B (2012/11/30)
Ver. 1.0

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

目次

講義資料

当日の OHP 資料

当日のOHP資料です。

講義で利用するサンプルプログラム

sample-001

Download : sample-001.c ( SJIS 版 )

sample-001.c
/*
 * 2012/11/16 sample-001.c
 *
 * a の平方根を求めるために 次方程式 ( x^2 - a = 0 ) の解を、虱潰し法で解く
 *		ただし、解は、一桁の自然数
 *
 */

#include <stdio.h>

/*
 *
 */

#define	YES		1
#define	NO		0

/*
 * x^2 - a = 0 ? : 論理式 P に相当する
 */

int check_formula ( int a, int x ) {

	if ( x * x - a == 0 ) {	/* 方程式を満すか ? */
		return YES;
	}

	return NO;

}

/*
 *	方程式 x^2 - a = 0 の解を、x_min 〜 x_max の範囲で探す
 *		見付かったら、その値を返す
 *		もし見付からなかったら、範囲外の数 ( x_max + 1 ) を返す
 */

int solve_formal ( int a, int x_min, int x_max ) {
	int x;

	for ( x = x_min; x <= x_max; x++ ) {		/* x = x_min 〜 x_max */
		if ( check_formula ( a, x ) == YES ) {	/* 見付かった */
			return x;							/* その値を返す */
		}
	}

	/*
	 * 見付からなかったので..
	 */

	 return x_max + 1;	/* 範囲の外である数を返す */

}

/*
 *	x^2 - a = 0 の整数解を求める
 */

int main ( void ) {
	int a;	/* x^2 - a = 0 の a */

	int x_min;
	int x_max;	/* F = { x | x_min <= x <= x_max } */

	int x;		/* 答の候補 */

	/*
	 *	[Input]
	 */

	/*
	 *	P(x) == ( x^2 - a = 0 )
	 */

	printf ( "方程式 x^2 - a = 0 の整数解 ( a の平方根 ) を搜します。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%d", &a );

	/*
	 *	F = { x | x_min <= x <= x_max }
	 */

	printf ( "x の取り得る範囲を指定してください\n" );
	printf ( "\t最小値 : " );
	scanf ( "%d", &x_min );
	printf ( "\t最大値 : " );
	scanf ( "%d", &x_max );

	/*
	 *	[Process]
   	 */

	/*
	 * 「 \exists x \in F[P(x)] 」の探索による証明
	 */

	x = solve_formal ( a, x_min, x_max );

	/*
	 *	[Output]
	 */

	if ( x > x_max ) {
		printf ( "方程式 x^2 - %d = 0 の解を %d 〜 %d の範囲の整数からは見つける事ができませんでした。\n", a, \
    x_min, x_max );
	} else {	/* 答が見つかった */
		printf ( "方程式 x^2 - %d = 0 の解は %d です。\n", a, x );
	}

	/*
	 *
	 */

	 return 0;

}

/*
 *
 */
入力例
16
0
10
sample-001.c の実行結果
C:\usr\c>sample-001<  sample-001.in
方程式 x^2 - a = 0 の整数解 ( a の平方根 ) を搜します。
 a の値を入力してください : 16
x の取り得る範囲を指定してください
	最小値 : 0
	最大値 : 10
方程式 x^2 - 16 = 0 の解は 4 です。
C:\usr\c> 

sample-002

Download : sample-002.c ( SJIS 版 )

sample-002.c
/*
 * 2012/11/16 sample-002.c
 *
 * a の平方根を求めるために 次方程式 ( x^2 - a = 0 ) の解を、虱潰し法で解く
 *		ただし、解は、小数点第ニ位まで求める
 *
 */

#include <stdio.h>
#include <math.h>				/* abs を利用するので.. */

/*
 */

#define	EPSILON	(10e-2)				/* 精度 (小数点第ニ位) */

/*
 * f(x) = x^2 - a の計算を行う (結果は、浮動小数点数型)
 */

double function ( double a, double x ) {

	return x * x - a;

}

/*
 *	方程式 x^2 - a = 0 の解を、x_min 〜 x_max の範囲で探す
 *		見付かったら、その値を返す
 *		もし見付からなかったら、範囲外の数 ( x_max + 1 ) を返す
 */

double solve_formal ( double a, double x_min, double x_max ) {
	double x;

	for ( x = x_min; x <= x_max; x = x + EPSILON ) {	/* x = x_min 〜 x_max */

		/*
		 * この計算では誤差があるので、
		 *			P(x) は「f(x)=
		 * ではなく
		 *			P(x) は「 |f(x)| < ε」となる
		 *
		 * [注意] fabs は 浮動小数点数の絶対値を計算する
		 */

		if ( fabs ( function ( a, x ) ) < EPSILON ) {
			return x;									/* 十分に解に近い値 */
		}
	}

	/*
	 * 見付からなかったので..
	 */

	 return x_max + 1;	/* 範囲の外である数を返す */

}

/*
 *	x^2 - a = 0 の解を小数点第二位まで求める
 */

int main ( void ) {
	double a;	/* x^2 - a = 0 の a */

	double x_min;
	double x_max;	/* F = { x | x_min <= x <= x_max } */

	double x;		/* 答の候補 */

	/*
	 *	[Input]
	 */

	/*
	 *	P(x) == ( x^2 - a = 0 )
	 */

	printf ( "方程式 x^2 - a = 0 の解 ( a の平方根 ) を小数点第二位まで求めるます。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%lf", &a );

	/*
	 *	F = { x | x_min <= x <= x_max }
	 */

	printf ( "x の取り得る範囲を指定してください\n" );
	printf ( "\t最小値 : " );
	scanf ( "%lf", &x_min );
	printf ( "\t最大値 : " );
	scanf ( "%lf", &x_max );

	/*
	 *	[Process]
   	 */

	/*
	 * 「 \exists x \in F[P(x)] 」の探索による証明
	 */

	x = solve_formal ( a, x_min, x_max );

	/*
	 *	[Output]
	 */

	if ( x > x_max ) {
		printf ( "方程式 x^2 - %lf = 0 の解を %lf 〜 %lf の範囲からは見つける事ができませんでした。\n", a, \
    x_min, x_max );
	} else {	/* 答が見つかった */
		printf ( "方程式 x^2 - %lf = 0 の解は %lf です。\n", a, x );
		printf ( "誤差は %lf です。\n", function ( a, x ) );
	}

	/*
	 *
	 */

	 return 0;

}

/*
 *
 */
入力例
2
0
4
sample-002.c の実行結果
C:\usr\c>sample-002<  sample-002.in
方程式 x^2 - a = 0 の解 ( a の平方根 ) を小数点第二位まで求めるます。
 a の値を入力してください : 2.000000
x の取り得る範囲を指定してください
	最小値 : 0.000000
	最大値 : 4.000000
方程式 x^2 - 2.000000 = 0 の解は 1.400000 です。
誤差は -0.040000 です。
C:\usr\c> 

sample-003

Download : sample-003.c ( SJIS 版 )

sample-003.c
/*
 * 2012/11/16 sample-003.c
 *
 * a の平方根を求めるために 次方程式 ( x^2 - a = 0 ) の解を、
 *		二分法で解く
 *		ただし、解の精度は 10E-6 とする
 *
 */

#include <stdio.h>

/*
 *
 */

#define	EPSILON	(10e-6)				/* 精度 */

/*
 * f(x) = x^2 - a の計算を行う (結果は、浮動小数点数型)
 */

double function ( double a, double x ) {

	return x * x - a;
}

/*
 *	方程式 x^2 - a = 0 の解を、
 *  lower 〜 upper の範囲で二分法で、精度が EPSILON 以下の範囲で求める
 *	但し、以下の条件が成立しているものとする
 *
 *		     lower < upper
 *
 *		f(lower) < 0 < f(upper)
 *
 */

double solve_formal ( double a, double lower, double upper ) {
	double x;

	while ( upper - lower > EPSILON ) {			/* 区間が精度より広い */
		double middle = (upper + lower)/2.0;	/* 中点を求める */

		if ( function ( a, middle ) > 0.0 ) {	/* 解は middle の左にある */
			upper = middle;						/* upper を更新 */
		} else {								/* 解は middle の右 */
			lower = middle;						/* lower を更新 */
		}
	}

	/*
	 * 解は、区間 [ lower, upper ] 内にあり、その範囲は  EPSILON 以下
	 */

	return (upper + lower)/2.0;					/* 中点の解として返す */
}

/*
 *	方程式 x^2 - a = 0 の解を、二分法で求める
 */

int main ( void ) {
	double a;	/* x^2 - a = 0 の a */

	double x_min;
	double x_max;	/* F = { x | x_min <= x <= x_max } */

	double x;		/* 答の候補 */

	/*
	 *	[Input]
	 */

	/*
	 *	P(x) == ( x^2 - a = 0 )
	 */

	printf ( "方程式 x^2 - a = 0 の解 ( a の平方根 ) を小数点第二位まで求めるます。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%lf", &a );

	/*
	 *	F = { x | x_min <= x <= x_max }
	 */

	printf ( "x の取り得る範囲を指定してください\n" );
	printf ( "\t最小値 : " );
	scanf ( "%lf", &x_min );
	printf ( "\t最大値 : " );
	scanf ( "%lf", &x_max );

	/*
	 *	[Process]
   	 */

	/*
	 * 「 \exists x \in F[P(x)] 」の探索による証明
	 */

	x = solve_formal ( a, x_min, x_max );

	/*
	 *	[Output]
	 */

	printf ( "方程式 x^2 - %lf = 0 の解は %lf です。\n", a, x );
	printf ( "誤差は %lf です。\n", function ( a, x ) );

	/*
	 *
	 */

	 return 0;

}

/*
 *
 */
入力例
2
0
4
sample-003.c の実行結果
C:\usr\c>sample-003<  sample-003.in
方程式 x^2 - a = 0 の解 ( a の平方根 ) を小数点第二位まで求めるます。
 a の値を入力してください : 2.000000
x の取り得る範囲を指定してください
	最小値 : 0.000000
	最大値 : 4.000000
方程式 x^2 - 2.000000 = 0 の解は 1.414211 です。
誤差は -0.000006 です。
C:\usr\c> 

講義中に作成したサンプルプログラム

本日の課題

課題 20121130-01

Download : 20121130-01.c ( SJIS 版 )

20121130-01.c
/*
 * DATE-DIR-QQQQ.c
 *
 * ニ次方程式 ( a x^2 + b x + c = 0 ) の解を、二分法で解く
 *		ただし、解の精度は 10E-6 とする
 *
 */

#include <stdio.h>

/*
 *
 */

#define	EPSILON	(10e-6)				/* 精度 */

/*
 * f(x) = a x^2 + b x + c の計算を行う
 */

double function ( double a, double b, double c, double x ) {

  return a * x * x + b... ;

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


}

/*
 *	方程式 f(x) = a x^2 + b x + c = 0 の解を、
 *  lower 〜 upper の範囲で二分法で、精度が EPSILON 以下の範囲で求める
 *	但し、以下の条件が成立しているものとする
 *
 *		     lower < upper
 *
 *		f(lower) < 0 < f(upper)
 *
 */

double solve_formal ( double a, double b, double c, double lower, double \
    upper ) {

	while ( upper - lower > EPSILON ) {			/* 区間が精度より広い */
		double middle = (upper + lower)/2.0;	/* 中点を求める */

		if ( function ( a, b, c, middle ) > 0.0 ) {	/* 解は middle の左にある */

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

		} else {									/* 解は middle の右 */
			lower = middle;							/* upper を更新 */
		}
	}

	/*
	 * 解は、区間 [ lower, upper ] 内にあり、その範囲は  EPSILON 以下
	 */

	return (upper + lower)/2.0;					/* 中点の解として返す */
}

/*
 *	a x^2 + b x + c = 0 の解を
 */

int main ( void ) {
	double a;
	double b;
	double c;		/* a x^2 + b x + c = 0 の a, b, c */

	double x_min;
	double x_max;	/* 探索区間は [x_min,x_max] */

	double x;		/* 答の候補 */

	/*
	 *	[Input]
	 */

	/*
	 *	f(x) = a x^2 + b x + c
	 */

	printf ( "方程式 a x^2 + b x + c = 0 の解を二分法で搜します。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%lf", &a );
	printf ( " b の値を入力してください : " );
	scanf ( "%lf", &b );
	printf ( " c の値を入力してください : " );
	scanf ( "%lf", &c );

	/*
	 *	探索区間 : [x_min,x_max]
	 */

	printf ( "x の探索区間を入力してください\n" );
	printf ( "\t最小値 : " );
	scanf ( "%lf", &x_min );
	printf ( "\t最大値 : " );
	scanf ( "%lf", &x_max );

	/*
	 *	[Process]
   	 */

	x = solve_formal ( a, b, c, x_min, x_max );

	/*
	 *	[Output]
	 */

	printf ( "方程式 %lf x^2 + -1.000000 x + -2.000000 = 0 の解は 2.000003 です。\n",a \
    );
	printf ( "誤差は 0.000009 になります。\n" );

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


	/*
	 *
	 */

	 return 0;

}

/*
 *
 */
入力例
1
-1
-2
0
10
20121130-01.c の実行結果
C:\usr\c\> 20121130-01
方程式 a x^2 + b x + c = 0 の解を二分法で搜します。
 a の値を入力してください : 1.000000
 b の値を入力してください : -1.000000
 c の値を入力してください : -2.000000
x の探索区間を入力してください
	最小値 : 0.000000
	最大値 : 10.000000
方程式 1.000000 x^2 + -1.000000 x + -2.000000 = 0 の解は 2.000003 です。
誤差は 0.000009 になります。
C:\usr\c\> 

課題 20121130-02

Download : 20121130-02.c ( SJIS 版 )

20121130-02.c
/*
 * DATE-DIR-QQQQ.c
 *
 * ニ次方程式 ( x^5 + a = 0 ) の解を、二分法で解く
 *		ただし、解の精度は 10E-6 とする
 *
 */

#include <stdio.h>

/*
 *
 */

#define	EPSILON	(10e-6)				/* 精度 */

/*
 * f(x) = x^5 + a の計算を行う
 */

double function ( double a, double x ) {


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


}

/*
 *	方程式 f(x) = x^5 + a = 0 の解を、
 *  lower 〜 upper の範囲で二分法で、精度が EPSILON 以下の範囲で求める
 *	但し、以下の条件が成立しているものとする
 *
 *		     lower < upper
 *
 *		f(lower) < 0 < f(upper)
 *
 */

double solve_formal ( double a, double lower, double upper ) {

	while ( upper - lower > EPSILON ) {			/* 区間が精度より広い */
		double middle = (upper + lower)/2.0;	/* 中点を求める */

		if ( function ( a, middle ) > 0.0 ) {	/* 解は middle の左にある */

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

		} else {									/* 解は middle の右 */
			lower = middle;							/* upper を更新 */
		}
	}

	/*
	 * 解は、区間 [ lower, upper ] 内にあり、その範囲は  EPSILON 以下
	 */

	return (upper + lower)/2.0;					/* 中点の解として返す */
}

/*
 *	a x^2 + b x + c = 0 の解を
 */

int main ( void ) {
	double a;		/* x^5 + a = 0 の a */
	double b;
	double c;

	double x_min;
	double x_max;	/* 探索区間は [x_min,x_max] */

	double x;		/* 答の候補 */

	/*
	 *	[Input]
	 */

	/*
	 *	f(x) = x^5 + a
	 */

	printf ( "方程式 x^5 + a = 0 の解を二分法で搜します。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%lf", &a );

	/*
	 *	探索区間 : [x_min,x_max]
	 */

	printf ( "x の探索区間を入力してください\n" );
	printf ( "\t最小値 : " );
	scanf ( "%lf", &x_min );
	printf ( "\t最大値 : " );
	scanf ( "%lf", &x_max );

	/*
	 *	[Process]
   	 */

	x = solve_formal ( a, x_min, x_max );

	/*
	 *	[Output]
	 */


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


	/*
	 *
	 */

	 return 0;

}

/*
 *
 */
入力例
-2
0
2
20121130-02.c の実行結果
C:\usr\c\> 20121130-02
方程式 x^5 + a = 0 の解を二分法で搜します。
 a の値を入力してください : -2.000000
x の探索区間を入力してください
	最小値 : 0.000000
	最大値 : 2.000000
方程式 x^5 + -2.000000 = 0 の解は 1.148701 です。
誤差は 0.000021 になります。
C:\usr\c\> 

課題 20121130-03

Download : 20121130-03.c ( SJIS 版 )

20121130-03.c
/*
 * DATE-DIR-QQQQ.c
 *
 * ニ次方程式 ( a x^2 + b x + c = 0 ) の解を、公式で解く
 *
 */

#include <stdio.h>
#include <math.h>		/* sqrt を利用するので.. */

/*
 * f(x) = a x^2 + b x + c の計算を行う (誤差計算のためにだけ利用)
 */

double function ( double a, double b, double c, double x ) {


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


}

/*
 *	方程式 f(x) = a x^2 + b x + c = 0 の解を、
 *  公式の一方
 *
 *        -b + \sqrt{ b^2 - 4 a c }
 *	x = ---------------------------
 *               2 a
 * x = ( - b + sqrt( b * b - 4 * a * c ) ) / ( 2 * a )
 * x = \frac{-b + \sqrt{ b^2 - 4 a c }}{2a}
 *
 *  を利用して解く。
 */

double solve_formal ( double a, double b, double c ) {


  return /* ここに (-b .. ) .. / ( 2 * a ) を記入 */ ;

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


}

/*
 *	a x^2 + b x + c = 0 の解を公式で求める
 */

int main ( void ) {
	double a;
	double b;
	double c;		/* a x^2 + b x + c = 0 の a, b, c */

	double x;		/* 答の候補 */

	/*
	 *	[Input]
	 */

	/*
	 *	f(x) = a x^2 + b x + c
	 */

	printf ( "方程式 a x^2 + b x + c = 0 の解を二分法で搜します。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%lf", &a );
	printf ( " b の値を入力してください : " );
	scanf ( "%lf", &b );
	printf ( " c の値を入力してください : " );
	scanf ( "%lf", &c );

	/*
	 *	[Process]
   	 */

	x = solve_formal ( a, b, c );

	/*
	 *	[Output]
	 */


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


	/*
	 *
	 */

	 return 0;

}

/*
 *
 */
入力例
1
-1
-2
0
10
20121130-03.c の実行結果
C:\usr\c\> 20121130-03
方程式 a x^2 + b x + c = 0 の解を二分法で搜します。
 a の値を入力してください : 1.000000
 b の値を入力してください : -1.000000
 c の値を入力してください : -2.000000
方程式 1.000000 x^2 + -1.000000 x + -2.000000 = 0 の解は 2.000000 です。
誤差は 0.000000 になります。
C:\usr\c\> 

Links

関連 Link

アルゴリズム

計算量