演習問題5解答例

問1 大人と子供の判断
問2 正,負,及び,0 の判断
問3 成績の判断
問4 時間と分の変換
問5 閏年の判定
問6 正弦の値の出力
問7 和の計算
問8 条件付き和の計算
問9 個数のカウント
問10 直列及び並列の抵抗値
問11 n!
問12 nr
問13 3n+1
問14 複数人の成績の判定とその割合
問15 複数人の給与支払いに必要な紙幣の数(ファイル)
問16 九九の表の出力
問17 数字の分離
問18 1 であるビット数のカウント
問19 未知個数データの最大値と最小値(ファイル)
問20 n クラス(各クラス: m 人)の中の最大値
問21 ニュートン法
問22 二分法
問23 台形則

[問1]年齢を読み込み,20 歳以上なら「大人」,そうでなければ「子供」と出力するプログラムを書け.
/****************************/
/* 大人と子どもの識別       */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int nenrei;
/*
     年齢の入力
*/
	printf("年齢を入力してください ");
	scanf("%d", &nenrei);
/*
     判断
*/
	if (nenrei >= 20)
		printf("   大人\n");
	else
		printf("   子供\n");

	return 0;
}
		
[問2]一つの整数データを読み込み,その値がゼロなら「 0 」,正なら「正」,それ以外なら「負」と出力するプログラムを,if 文を使用して書け.
/****************************/
/* 正,負,ゼロの識別       */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int kazu;
/*
     年齢の入力
*/
	printf("数字を入力してください ");
	scanf("%d", &kazu);
/*
     判断
*/
	if (kazu == 0)
		printf("   0\n");
	else {
		if (kazu > 0)
			printf("   正\n");
		else
			printf("   負\n");
	}

	return 0;
}
		
[問3]試験の点数を読み込み,その点数が
60 点未満なら「不可」
60 点以上で 70 点未満なら「可」
70 点以上で 80 点未満なら「良」
80 点以上なら「優」
と出力するプログラムを書け
/****************************/
/* 成績の判定               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int ten;
/*
      点数の入力
*/
	printf("点数は? ");
	scanf("%d", &ten);
/*
      判定
*/
	if (ten < 60)
		printf("   不可\n");
	else {
		if (ten < 70)
			printf("   可\n");
		else {
			if (ten < 80)
				printf("   良\n");
			else
				printf("   優\n");
		}
	}

	return 0;
}
		
[問4]時間と分の変換を行うプログラムを書け.つまり,1 時間 20 分なら 80 分,また,90 分なら 1 時間 30 分に変換する.
/****************************/
/* 時間の変換               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int time, min, sw;
/*
      変換方法の入力
*/
	printf("変換方法は(0:時間→分, 1:分→時間)? ");
	scanf("%d", &sw);
/*
     データと変換
*/
	if (sw == 0) {
		printf("   時間と分は? ");
		scanf("%d %d", &time, &min);
		min = 60 * time + min;
		printf("      %d 分です\n",min);
	}
	else {
		printf("   分は? ");
		scanf("%d", &min);
		time = min / 60;
		min  = min % 60;
		printf("      %d 時間 %d 分です\n", time, min);
	}

	return 0;
}
		
[問5]閏年の判定を行うプログラムを書け.閏年は,年号が 4 で割り切れ,100 で割り切れない年である.ただし,400 で割り切れる年は含む.
/****************************/
/* 閏年の判定               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int year;
/*
     年の入力
*/
	printf("年を入力して下さい? ");
	scanf("%d", &year);
/*
     判定
*/
	if (((year%4 == 0) && (year%100 != 0)) || (year%400 == 0))
		printf("   閏年です\n");
	else
		printf("   閏年ではありません\n");

	return 0;
}
		
[問6]1 度,2 度,・・・,及び,90 度に対し,各角度とその正弦の値(関数 sin )を出力するプログラムを書け(注:ヘッダファイル math.h も必要).
/***************************/
/* 正弦の計算              */
/*      coded by Y.Suganum */
/***************************/
#include <stdio.h>
#include <math.h>

int main()
{
	double pi, unit, x, y;
	int i1;
/*
     初期設定
*/
	pi   = 4.0 * atan(1.0);
	unit = pi / 180.0;
	x    = 0.0;
/*
     計算と出力
*/
	for (i1 = 1; i1 <= 90; i1++) {
		x += 1.0;
		y  = sin(x * unit);
		printf("角度 %4.1f 正弦 %7.5f\n", x, y);
	}

	return 0;
}
		
[問7]次の式の値を計算し,出力するプログラムを書け
  (1)1.02+・・・+500.02
  (2)1/1 + 1/2 + 1/3 + ・・・ + 1/20
/***************************/
/* 2乗和等の計算          */
/*      coded by Y.Suganum */
/***************************/
#include <stdio.h>

int main()
{
	double sum1, sum2, x;
	int i1;
/*
     初期設定
*/
	sum1 = 0.0;
	sum2 = 0.0;
/*
     計算
*/
	x = 0.0;
	for (i1 = 0; i1 < 500; i1++) {
		x    += 1.0;
		sum1 += x * x;
	}

	x = 0.0;
	for (i1 = 0; i1 < 20; i1++) {
		x    += 1.0;
		sum2 += 1.0 / x;
	}
/*
     出力
*/
	printf("和=%f %f\n", sum1, sum2);

	return 0;
}
		
[問8]n (入力)個のデータを読み込み,100 以上のデータ,及び,100 未満のデータの和をそれぞれ求めるプログラムを書け.
/**************************************/
/* 100以上,及び,100未満のデータの和 */
/*      coded by Y.Suganum            */
/**************************************/
#include <stdio.h>

int main()
{
	int i1, n, sum1, sum2, x;
/*
     初期設定
*/
	sum1 = 0;
	sum2 = 0;
/*
     データの数の入力
*/
	printf("データの数は? ");
	scanf("%d", &n);
/*
     計算
*/
	for (i1 = 0; i1 < n; i1++) {
		printf("   データは? ");
		scanf("%d", &x);
		if (x < 100)
			sum1 += x;
		else
			sum2 += x;
	}
/*
     出力
*/
	printf("100未満の和 %d  100以上の和 %d\n", sum1, sum2);

	return 0;
}
		
[問9]与えられた n 個のデータ内にある正の数と負の数の個数を出力するプログラムを書け.
/***************************/
/* 正と負の数の個数        */
/*      coded by Y.Suganum */
/***************************/
#include <stdio.h>

int main()
{
	int i1, n, sei, hu, x;
/*
     初期設定
*/
	sei = 0;
	hu  = 0;
/*
     データの数の入力
*/
	printf("データの数は? ");
	scanf("%d", &n);
/*
     データを入力し数える
*/
	for (i1 = 0; i1 < n; i1++) {
		printf("   データは? ");
		scanf("%d", &x);
		if (x != 0) {
			if (x > 0)
				sei++;
			else
				hu++;
		}
	}
/*
     出力
*/
	printf("正の数 %d  負の数 %d\n", sei, hu);

	return 0;
}
		
[問10]n 個の抵抗(入力)を直列または並列に接続したときの抵抗を計算するプログラムを書け.
/***************************/
/* 抵抗の直列と並列        */
/*      coded by Y.Suganum */
/***************************/
#include <stdio.h>

int main()
{
	double cho, hei, x;
	int i1, n;
/*
     初期設定
*/
	cho = 0.0;
	hei = 0.0;
/*
     データの数の入力
*/
	printf("抵抗の数は? ");
	scanf("%d", &n);
/*
     抵抗の計算
*/
	for (i1 = 0; i1 < n; i1++) {
		printf("   抵抗の値は? ");
		scanf("%lf", &x);
		cho += x;
		hei += 1.0 / x;
	}

	hei = 1.0 / hei;
/*
     出力
*/
	printf("直列結合 %f  並列結合 %f\n", cho, hei);

	return 0;
}
		
[問11]n の値を読み込んだ後,n! を計算し出力するプログラムを書け.
/****************************/
/* n!の計算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	double kai;
	int i1, n;
/*
     初期設定
*/
	kai = 1.0;
/*
     nの入力
*/
	printf("nの値は? ");
	scanf("%d", &n);

	if (n < 0)
		printf("データが不適当です!\n");
/*
     計算
*/
	else {
		for (i1 = 2; i1 <= n; i1++)
			kai *= i1;
/*
     出力
*/
		printf("   n!=%f\n", kai);
	}

	return 0;
}
		
[問12]n,r の値を読み込んだ後,nr( = n! / (r! ( n - r )!) )を計算するプログラムを書け.
/****************************/
/* nCrの計算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	double c, nk, rk, n_rk;
	int i1, n, r;
/*
          データの入力
*/
	printf("nとrは? ");
	scanf("%d %d", &n, &r);

	if (n < 0 || r < 0 || r > n)
		printf("データが不適当です!\n");
/*
          実行
*/
	else {
		nk = 1.0;
		for (i1 = 2; i1 <= n; i1++)
			nk *= i1;
		rk = 1.0;
		for (i1 = 2; i1 <= r; i1++)
			rk *= i1;
		n_rk = 1.0;
		for (i1 = 2; i1 <= (n-r); i1++)
			n_rk *= i1;
		c = nk / (rk * n_rk);
		printf("   nCr= %f\n", c);
	}

	return 0;
}
		
[問13]正の整数値 n を読み込み,偶数の時はその値を 2 で割り,また,奇数の時はその値を 3 倍したものに 1 を加えるという処理を n の値が 1 になるまで繰り返すためのプログラムを書け.ただし,1 回の演算を行う毎に現在の n の値を表示するものとする.
/****************************/
/* 3n+1                 */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int n;
/*
     nの入力
*/
	printf("nの値は? ");
	scanf("%d", &n);
	printf("   n=%d\n", n);
/*
     計算
*/
	while (n > 1) {
		if (n%2 == 0)
			n = n / 2;
		else
			n = 3 * n + 1;
		printf("   n=%d\n", n);
	}

	return 0;
}
		
[問14]n (入力)人の試験の点を入力した後,不可,可,良,及び,優の割合(%)を計算し,出力するプログラムを書け.ただし,
不可: 50 点未満
可 : 50 点から 60 点未満
良 : 60 点から 80 点未満
優 : 80 点以上
とする.
/****************************/
/* 優、良、可、不可の割合   */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	double a0, a1, a2, a3;
	int i1, m, n;
/*
          初期設定
*/
	a0 = 0.;
	a1 = 0.;
	a2 = 0.;
	a3 = 0.;
/*
          入力
*/
	printf("人数は? ");
	scanf("%d",&n);
	for (i1 = 0; i1 < n; i1++) {
		printf("   点数は ");
		scanf("%d", &m);
		if (m < 50)
			a0 += 1.;
		else {
			if (m < 60)
				a1 += 1.;
			else {
				if (m < 80)
					a2 += 1.;
				else
					a3 += 1.;
			}
		}
	}
/*
          計算と出力
*/
	a0 = a0 / n * 100.;
	a1 = a1 / n * 100.;
	a2 = a2 / n * 100.;
	a3 = a3 / n * 100.;
	printf("不可=%f%\n", a0);
	printf("  可=%f%\n", a1);
	printf("  良=%f%\n", a2);
	printf("  優=%f%\n", a3);

	return 0;
}
		
[問15]n 人に給与を支払うものとする.n 及び各人の給与の額をファイルから読み込み,すべての人に給与を釣り銭がないように支払うために必要な 10,000 円札,5,000 円札,1,000 円札,500 円硬貨,及び,100 円硬貨の合計枚数を出力するプログラムを書け.ただし,給与の最小単位は 100 円であるものとする.
/****************************/
/* 給与の計算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int i1, kyuyo, k1, n, m10000, m5000, m1000, m500, m100;
	FILE *in;
/*
          初期設定とファイルのオープン
*/
	m10000 = 0;
	m5000  = 0;
	m1000  = 0;
	m500   = 0;
	m100   = 0;

	in = fopen("kyuyo", "r");
/*
     データの読み込みと計算
*/
	fscanf(in,"%d", &n);
	for (i1 = 0; i1 < n; i1++) {
		fscanf(in, "%d", &kyuyo);
		k1      = kyuyo / 10000;
		kyuyo  -= k1 * 10000;
		m10000 += k1;
		k1      = kyuyo / 5000;
		kyuyo  -= k1 * 5000;
		m5000  += k1;
		k1      = kyuyo / 1000;
		kyuyo  -= k1 * 1000;
		m1000  += k1;
		k1      = kyuyo / 500;
		kyuyo  -= k1 * 500;
		m500   += k1;
		k1      = kyuyo / 100;
		m100   += k1;
	}
/*
     出力
*/
	printf("10000円札 %d 枚\n",m10000);
	printf("5000円札 %d 枚\n",m5000);
	printf("1000円札 %d 枚\n",m1000);
	printf("500円硬貨 %d 枚\n",m500);
	printf("100円硬貨 %d 枚\n",m100);

	fclose(in);

	return 0;
}
		
[問16]九九の表を出力するプログラムを書け.
/****************************/
/* 九九の表の出力           */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int i1, i2;

	for (i1 = 1; i1 <= 9; i1++) {
		for (i2 = 1; i2 <= 9; i2++)
			printf("%3d", i1*i2);
		printf("\n");
	}

	return 0;
}
		
[問17]正の整数を入力し,それを各桁毎に分解し,それらの数字を正順及び逆順に,間に 1 つ以上の空白をあけて出力するプログラムを書け.例えば,12345 と入力したら,次のように出力することになる.ただし,整数の桁数は最大 9 桁であるとする.
  1 2 3 4 5
  5 4 3 2 1
/****************************/
/* 数字の分離               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int n, m, k = 100000000, k1, sw = 0;

	printf("正の整数を入力してください ");
	scanf("%d", &n);
					// 正順
	m = n;
	while (k > 0) {
		k1  = m / k;
		m  %= k;
		k  /= 10;
		if (k1 > 0) {
			sw = 1;
			printf("%d ", k1);
		}
		else {
			if (sw > 0)
				printf("%d ", k1);
		}
	}
	printf("\n");
					// 逆順
	m = n;
	while (m > 0) {
		k1  = m % 10;
		m  /= 10;
		printf("%d ", k1);
	}

	return 0;
}
		
[問18]整数型データの中で 1 になっているビットの数を出力するプログラムを書け.
/****************************/
/* 1のビット数を数える     */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int i1, n, kazu = 0;
	unsigned int mask = 0x80000000;
/*
     整数の入力
*/
	printf("整数を入力して下さい ");
	scanf("%d", &n);
/*
     個数を数える
*/
	for (i1 = 0; i1 < 32; i1++) {
		if ((mask & n) != 0)
			kazu++;
		mask >>= 1;
	}

	printf("1のビット数は %d\n", kazu);

	return 0;
}
		
[問19]複数個(未知)の実数データをファイルから読み込み,その最大値と最小値を出力するプログラムを書け.
/************************************/
/* 最大値と最小値の計算(未知個数) */
/*      coded by Y.Suganuma         */
/************************************/
#include <stdio.h>

int main()
{
	double max = 0, min = 0, x;
	int sw = 0;
	FILE *in;
/*
          データの入力と比較
*/
	in = fopen("input", "r");

	while (EOF != fscanf(in, "%lf", &x)) {
		if (sw == 0) {
			sw  = 1;
			max = x;
			min = x;
		}
		else {
			if (x > max)
				max = x;
			else {
				if (x < min)
					min = x;
			}
		}
	}
/*
          結果の出力
*/
	printf("最大値= %f   最小値= %f\n", max, min);

	return 0;
}
		
[問20]ある学年に n (入力)クラスあり,各クラスには m (入力,クラス毎に異なる)人の生徒がいるものとする.全員に対しある試験を実施したとき,学年で最高点をとった生徒の点数及びその生徒が属するクラス番号を出力するプログラムを書け(最高点の生徒は一人だけであるとする).
/****************************/
/* 最高点とそのそのクラス   */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int main()
{
	int i1, i2, max, max_c = 0, n, m, ten;
/*
          初期設定
*/
	max  = 0;
/*
          データの入力と計算
*/
	printf("クラスの数は? ");
	scanf("%d", &n);
	for (i1 = 0; i1 < n; i1++) {
		printf("%d 番目のクラスの人数は ", i1+1);
		scanf("%d", &m);
		for (i2 = 0; i2 < m; i2++) {
			printf("     %d 番目の人の点は? ", i2+1);
			scanf("%d", &ten);
			if (ten > max) {
				max_c = i1 + 1;
				max   = ten;
			}
		}
	}
/*
          出力
*/
	printf("最高点はクラス %d の %d 点\n", max_c, max);

	return 0;
}
		
[問21]ニュートン法により次式の根を求めるためのプログラムを書け.
f(x) = ex - 3x = 0
ただし,ニュートン法とは,関数 f(x) が単調連続で変曲点が無く,かつ,微分可能であるとき利用できる方法であり,根の適当な初期値 x0 から始めて,反復公式
xn+1 = xn - f(xn) / f'(xn)
を繰り返すことによって非線形方程式の解を求める方法である.この方法の幾何学的意味は右図に示すとおりである.収束判定の条件としては,
|xn+1 - xn| < ε
|f(xn+1) - f(xn)| < ε
|f(xn)| < ε
などがある.
/****************************/
/* ニュートン法             */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <math.h>

int main()
{
	double g, dg, eps1, eps2, x, x0, x1, s, ds;
	int max, ind, sw;
/*
          データの入力
*/
	printf("eps1? ");
	scanf("%lf", &eps1);
	printf("eps2? ");
	scanf("%lf", &eps2);
	printf("最大試行回数? ");
	scanf("%d", &max);
	printf("初期値? ");
	scanf("%lf", &x0);
/*
          初期設定
*/
	x1  = x0;
	x   = x1;
	ind = 0;
	sw  = 0;
/*
          実行
*/
	while (sw == 0 && ind >= 0) {
		sw  = 1;
		ind = ind + 1;
		g   = exp(x1) - 3.0 * x1;
		if (fabs(g) > eps2) {
			if (ind <= max) {
				dg = exp(x1) - 3.0;
				if (fabs(dg) > eps2) {
					x = x1 - g / dg;
					if (fabs(x-x1) > eps1) {
						x1 = x;
						sw = 0;
					}
				}
				else
					ind = -1;
			}
			else
				ind = -1;
		}
	}
/*
          出力
*/
	if (ind < 0)
		printf("解を求めることができません!\n");
	else {
		s  = exp(x) - 3.0 * x;
		ds = exp(x) - 3.0;
		printf("ind=%d  x=%f  f=%f  df=%f\n", ind, x, s, ds);
	}

	return 0;
}
		
[問22]二分法により次式の根を求めるためのプログラムを書け.
f(x) = ex - 3x = 0
ただし,二分法は,関数 f(x) が区間 [a, b] で連続で,かつ,根が 1 つだけ存在するとき利用できる方法である.従って,f(a)f(b) < 0 となる.区間 [a, b] の中点 c を
c = 0.5 * (a + b)
で求め,f(c) の値を計算し,f(a)f(c) < 0 なら
b = c,f(b) = f(c)
そうでなければ
a = c,f(a) = f(c)
と置き換え,根の存在区間を半分に縮小する.この操作を,
|b - a| < ε
が満足されるまで繰り返すことによって解を求める.
/****************************/
/* 二分法                   */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <math.h>

int main()
{
	double eps1, eps2, f, f1, f2, x, x1, x2;
	int max, ind, sw;
/*
          データの入力
*/
	printf("eps1? ");
	scanf("%lf", &eps1);
	printf("eps2? ");
	scanf("%lf", &eps2);
	printf("最大試行回数? ");
	scanf("%d", &max);
	sw = 0;
	while (sw == 0) {
		printf("初期値(2つ)? ");
		scanf("%lf %lf", &x1, &x2);
		f1  = exp(x1) - 3.0 * x1;
		f2  = exp(x2) - 3.0 * x2;
		if (f1*f2 < 0.0)
			sw = 1;
	}
/*
          初期設定
*/
	f1  = exp(x1) - 3.0 * x1;
	f2  = exp(x2) - 3.0 * x2;
	ind = 0;
	sw  = 0;
/*
          実行
*/
	while (sw == 0 && ind >= 0) {
		ind++;
		sw = 1;
		x  = 0.5 * (x1 + x2);
		f  = exp(x) - 3.0 * x;
		if (fabs(f) > eps2) {
			if (ind <= max) {
				if (fabs(x1-x2) > eps1) {
					sw = 0;
					if (f*f1 < 0.0) {
						x2 = x;
						f2 = f;
					}
					else {
						x1 = x;
						f1 = f;
					}
				}
			}
			else
				ind = -1;
		}
	}
/*
          出力
*/
	if (ind < 0)
		printf("解を求めることができません!\n");
	else
		printf("ind=%d  x=%f  f= %f\n", ind, x, f);

	return 0;
}
		
[問23]台形則により次の関数の任意区間の積分値を計算するプログラムを書け.
f(x) = (2π)-0.5-x*x/2
ただし,台形則は,積分区間 [x1, x2] を n 個の,幅
h = (x2 - x1) / n
の小区間に分け,各区間の面積を右図のような台形で近似して,積分値を計算する方法である.従って,積分値 S は次のように書ける.
  S = 0.5h{f(x1) + 2(f(x1+h) + f(x1+2h) + ・・・ + f(x2-h)) + f(x2)}
/****************************/
/* 台形則による積分         */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <math.h>

int main()
{
	double f1, f2, h, s, x, x1, x2;
	int i1, n;
/*
          データの入力
*/
	printf("積分区間は? ");
	scanf("%lf %lf", &x1, &x2);
	printf("分割数は? ");
	scanf("%d", &n);
/*
          初期設定
*/
	f1 = exp(-0.5 * x1 * x1) / 2.506628275;
	f2 = exp(-0.5 * x2 * x2) / 2.506628275;
	s  = 0.5 * (f1 + f2);
	h  = (x2 - x1) / n;
	x  = x1 + h;
/*
          実行
*/
	for (i1 = 0; i1 < n-1; i1++) {
		s = s + exp(-0.5 * x * x) / 2.506628275;
		x = x + h;
	}
	s = s * h;
/*
          出力
*/
	printf("面積=%f\n", s);

	return 0;
}
		

菅沼ホーム 演習解答例目次 本文目次 付録 索引