back
last update 99/7/27 new 99/7/23(新規作成)

学籍番号

               

名前

                                          

静大プログラミング 期末試験 (by望月 7/27)

注意: 問1 (ボーナス問題) 2値符号を使って数値を表わす方法は, 何通りも存在する。
もっとも普通に使われるのは2進数であり, 例えば10ビット使うことが出来るのであれば, 0 〜 1023 (= 2 の 10乗 から 1を減じたもの) を表わすことが出来る。
日本古来の表わし方のひとつが,そろばんであり, 1個の5の玉と,4個の1の玉の位置で一桁を表わす。 これは,5ビットにより数字一つを表わすと考えられる。 10ビット使うことが出来るのであれば, 0 〜 99 を表わすことが出来る。

それでは,2進数と,そろばん方式について, お互いを比較してそれぞれの長所を述べよ。






問2 次のプログラム(抜粋)のなかの@, Aおのおのの演算は違った答えとなるというが, その理由を述べよ。
(注意:模擬試験とは数値が変えてあります。)
int a;
float b;

a = 10/7;         @
b = 10./7.;       A

問3 次のプログラム(抜粋)のなかの@〜Bにおいて, 指示された変数はいくらなのか述べなさい。
(注意:模擬試験とは数値も式も変えてあります。)
int a,b,c;

a = 2;
b = 3;
c = a + b;
               @ このとき c の値は? 
b = b + c;
               A このとき b の値は? 
a= a + b - c;
               B このとき a の値は? 


問4 次にあげる4つのプログラムは, 小さい数から順番に大きな数を表示するが, それぞれ幾つから幾つまで表示するか答えよ。
ヒント:ループの最初と,ループの最後に特に注意しよう。
(注意:模擬試験とは数値を変えてあります。)
int i;

i=1;
while(i<=4){
	printf("%d\n",i); 
	i=i+1;
}

int i;

i=1;
do{
	i=i+1;
	printf("%d\n",i); 
}while(i<=4);

int i;

for(i=1; i<4; i=i+1){
	printf("%d\n",i); 
}

int i;

i=1;
while(i>=0){
	if(i==4) break;
	i=i+1;
	printf("%d\n",i); 
}

問5 次のプログラム(抜粋)は, @の所では変数 a の値は 0 から 9 まで変化する。 if文により Aにて出力するのは a がいくつの時なのか, 値をすべて記せ。
(注意:模擬試験とはif文の条件式を変えてあります。)

int a;


for(a=0; a<10; a=a+1){
   printf("%d\n",a);      @
   if( (3<a) && (a<7) ){
      printf("  condition = true\n");      A
   }
}


問6 次のプログラム(抜粋)は,次の動作をするように作られた: しかし,@の部分 ( 複数行が入る可能性あり ) が未完成である。 ここを埋めて,正しく動作するようにしなさい。
(注意:模擬試験とは目的とする動作が多少変わってます。)
(注意:また,max という変数を使わなくしています。)
int byou[100],n,i,isaikou;

//この部分で,以下のように設定/入力
//     n : 最大の出席番号
//     byou[i] : 出席番号 i の人の点数
//     byou[1] から byou[n] が有効な数字

printf("1 番目の人の点数は,%d です。\n",byou[1]);
isaikou=1;
for(i=2; i<=n; i=i+1){
	printf("%d 番目の人は,%d 秒で走りました。\n",i ,byou[i]);

	@
	
		printf("この人は最高記録ではありません\n");
	}else{
		printf("最高記録の候補です\n");
		isaikou=i;
	};
}
printf("最高記録は %d 番目の人による %d 秒です。\n",isaikou ,byou[isaikou]);


問7 次のプログラム(抜粋)は,次の動作をするように作られた: しかし,このプログラムは,一部おかしい点がある。 (ここでは敢えて'おかしい'ということがどういう点か述べない) 正しく動作するにはどの部分をどう変更したら良いか答えなさい。
ヒント:n を 4 くらいに置いて,どういう動作が行われるか検討してみよう。
(注意:模擬試験とは異常動作の原因を変えてあります。)
int tensu[100],t,n,i,j;

for(i=0; i<100; i=i+1)
	tensu[i]=0;

//この部分で,以下のように設定/入力
//	n : 最大の出席番号 (1クラスは約80名とする)
//	tensu[i] : 出席番号 i の人の点数
//	tensu[1] から tensu[n] が有効な数字
//	tensu[0] は 0
//	tensu[n+1] から tensu[99] は 0

for(j=1; j<(n-1); j=j+1){
	for(i=(j+1); i<=n; i=i+1){
		if( tensu[j]>=tensu[i] ) {
			t=tensu[i];  //以下3行でならべ変え
			tensu[i]=tensu[j];
			tensu[j]=t;
		}
	}
}

for(j=1; j<=n; j=j+1){
	printf("%d 番目に低い点数は,%d です。\n", j, tensu[j]);
}


数値計算の問題 (関数も使って)
問8 x という数値の平方根を求めるには, 普通には sqrt という関数を用い,
  y = sqrt(x);
という風に用いる。

しかし,sqrt を使わなくても計算する方法がある。
ここでは,0 < x < 1 という x に対して, 有効桁数 5桁で,sqrt(x) とほぼ同じ値を返す関数を考えよう。
(教科書には p.83 にその方法が載っているが, ここでは別のスマートな方法を使おう。)

まずは,解の条件を明確にする。
  1. この場合,y から x に対して,x=y*y という式が成り立つ。
  2. x は 0.0 〜 1.0 であるため, y も 0.0 〜 1.0 の筈である。
  3. また,y は一つだけである。
このように,逆関数があり,解の下限と上限が決まり, 一意に決まるという3つの性質を持つことから, 次に述べるアルゴリズム(考え方)によって, 必ず正しい解を求めることが出来る。

解法のアルゴリズム(考え方):
  1. まず 解の候補として 変数 a, b を定義する。
    変数 a, b それぞれの初期値は 0.0 と 1,0 とする。
  2. (i)と(ii)の条件より,
    a*a < x < b*b
    という関係式が成り立つ。
  3. 次の操作により。(II)の関係式を満たしながら,a と b の差が縮まるよう値を変えて行く。
    1. c=(a+b)/2. を計算する。
    2. 解は,a*a 〜 c*c の間か,または,c*c 〜 b*b の間の何れかに存在する。
      どちらに存在するか判定し,それに応じて a または b の値を書き換える。
    3. 以上の作業により, a と b の差は,半分になった。
    4. 望みの精度に達するまでこの作業を繰り返す。
  4. a または b の値を解として表示する。
以上を C 言語に焼き直した正しく動作するプログラムを次に示す。

しかし,このプログラムは冗長度が高いため, 処理時間を考えるとベストな解とは言えない, もっと処理時間を短くするには,必要十分な動作をするよう書き換える必要がある。
そのためには何処をどう変更したら良いか答えなさい。
#include 
double f(double y)
{
	return(y * y);
}

main()
{
	double a,b,c,x;

	//	ここで,x に 0 から 1 までの値を設定する。

	a=0.0; b=1.0;
	while( (b-a) > 0.00001 ){
		c=(a+b)/2.0;
		if( (f(a) <= x) && (x < f(c)) ){
			b=c;
		}else if( (f(c) <= x) && (x <= f(b)) ){
			a=c;
		}else{
			printf("この関数はこのアルゴリズムでは扱えません。\n");
			exit();		//プログラム終了
		}
	}

	printf("%d の平方根は,%d です。\n", x, a);
}

注意:このアルゴリズムは「2分法」と呼ばれています。 先に述べた条件さえ満たしていれば,確実に解を求めることが出来ます。
例えば,ある計算機が,ライブラリの関係で, 指数関数は計算できても log を計算できなかったとします。 こんな時でも,同じアルゴリズムで log を求めることが出来ます。 その場合は,関数 f(x) を書き換えれば OK です。 但し,x の変域に気をつけるのをお忘れなく。