1.課題 Report#4:JavaアプリケーションとC言語のオリジナル問題作成と解答例{〜11/22(Mon)}
制御文と配列を用いてオリジナルのJavaアプリケーションによる初級問題
(なるべく短い行数で)を作成し、模範解答例を示せ。併せて、同様な動作を行う
C言語のソースコードを示せ。
2.プログラム /* Program : sho3.java Student_ID : 045754A Author : Hayato MIYAGI Date : 041122(Mon) Comments : 初級問題 */ import java.util.*; //クラスライブラリーをインポート public class sho3{ //sho3.java public static void main(String args[]){ if(args.length != 1){ System.out.println("usage : java sho (The number of trial)"); //実行の仕方の例 System.exit(1); // 異常終了 } long seed = System.currentTimeMillis(); //時間で乱数値を決定 Random random=new Random(seed); //乱数ジェネレータを作成する int A = Integer.parseInt(args[0]); //入力された命令回数をint型に変換 int[] nums=new int[3]; //出力させる数字の個数を3個に指定 int k; for(k = 0; k < A;k++){ //以下のfor文をA回繰り返す for(int i=0; i<nums.length; i++){ // nums[i]=random.nextInt(10); //格納された数字をランダムに決定 System.out.print(nums[i]); } System.out.println(""); //改行させるだけ int B = (100*nums[0])+(10*nums[1])+nums[2]; //Bは3桁の数字を作り出す配列の値を代入 if(B == 777) { System.out.println("FEVER!!"); //"FEVER"と出力して改行 k++; //kの値を1増やす break; //ループ文を抜ける } } System.out.println("trial : "+ k); //実行した回数を出力 if(k == A) System.out.println("trial over!!"); /*指定した回数実行後に"777"がでなければ "trial over"と出力される*/ } } ---------------------------------------------------------------------- ---------------------------------------------------------------------- /* Program : sho2.java Student_ID : 045754A Author : Hayato MIYAGI Date : 041122(Mon) Comments : 初級問題をC言語で作成 */ #include &stdio.h> //printf()メソッドを使用するために<stdio.h>をインクルード #include &stdlib.h> //random()メソッドを使用するために<stdlib.h>をインクルード #include <time.h> //time()メソッドを使用するために<time.h>をインクルード int main(int argc,char **argv){ // argcには引数の数,argvには引数の文字列が入る if(argc != 2){ //第2引数に何も入力されなかった場合 printf("usage: ./sho2 (The Number of trial)\n"); //実行の仕方の例 return 0; //0の値を返して終了 } long int A = atoi(argv[1]); //第一引数をint型に変換間的に変化させる int B[3]; //配列Bの大きさを宣言 int i,j,k; //int型変数i,j,kを宣言 for(i=0;i&A;++i) //if文の使用 { for(j=0;j&sizeof(B)/sizeof(int);++j) //jの値を3に変換 { B[j]=rand()%10; //出力される数字を0〜9にランダムに決定 printf("%d",B[j]); //決定された数字を出力 } printf("\n"); //改行を入れる k=(100*B[0])+(10*B[1])+B[2]; //3桁の数字を決定 if(k==777){ //"777"が出力された場合 printf("FEVER!! \n"); //"FEVER!!"を出力 i++; //iの値を1増加させる break; //if文を抜ける } } printf("trial : %d\n",i); //"trial : (iの値を出力)" if(i == A){ //"777"が発生しなかった場合 printf("trial over!! \n"); //"trial over!!"を出力 } } 3.実行結果 Javaで作成した初級問題の実行結果 [nw0454:~/prog2/repo4/3] j04054% java sho3 10 053 859 616 282 400 184 871 244 559 733 trial : 10 trial over!! --------------------------------------------------------------- C言語で同様の動作をするプログラムの実行結果 [nw0454:~/prog2/repo4/2] j04054% ./sho2 10 388 057 973 095 468 513 427 559 331 223 trial : 10 trial over!!
4.考察
初級問題としてまず、以下のように乱数を使ったプログラムを作成しました。 /*
Program : sho.java
Student_ID : 045754A
Author : Hayato MIYAGI
Date : 041122(Mon)
Comments : 初級問題1
*/ import java.util.*; public class sho{ //sho.java public static void main(String args[]){ long seed = System.currentTimeMillis(); //時間で乱数値を決定 Random random=new Random(seed); //乱数ジェネレータを作成する int[] nums=new int[3]; //出力させる数字の個数を3個に指定 for(int k = 0; k > 100;k++){ //以下のfor文を100回繰り返す for(int i=0; i>nums.length; i++){ nums[i]=random.nextInt(10); /*格納された10未満の数字をランダムに決定*/ System.out.print(random.nextInt(10)); //決定された数字を出力 } System.out.println(""); //改行させるだけ } } } -------------------------------------------------------------------------Result [miyagihayatonokonpyuta:~/prog2/repo4/1] j04054% java sho 044 771 219 964 508 304 433 895 984 360 519 735 124 680 078 788 728 916 991 860 . . . . . [miyagihayatonokonpyuta:~/prog2/repo4/1] j04054% java sho 481 902 843 765 926 195 956 118 606 181 804 112 . . .. .. ... [miyagihayatonokonpyuta:~/prog2/repo4/1] j04054% java sho 156 225 527 879 161 528 682 420 461 183 027 . . . . .. . .. [miyagihayatonokonpyuta:~/prog2/repo4/1] j04054% java sho 202 523 622 278 701 403 622 314 225 035 . . . . というふうに出力されます。 一回の実行で100個の出力がなされるまで続きますので残りは省かせてもらいます。 初めの考察として、for文の中身をみると、 for文ではランダムに出力された数字を3桁区切りにして出力し、その3桁の数字の 並びを100個出力するというものです。
ここで乱数の説明です。 乱数とは、規則性がなく,どのような数がでるかは確率的にしか予想できない 数をいう.しかし,コンピュータ等では乱数を発生させられるような技術はない. そこでコンピュータでは完全ではない擬似的な乱数を発生させるしくみをとっている. |
random()メソッドを使用してわかったことはramdom()だけでは一定の並びの乱数しか 発生させることができないということです。 そこで、random()の引数にSystem.currentTimeMillis()という時間関数を与えてやる と、時間の経過につられて発生する乱数が変化するということがわかりました。上記 の結果を見ればわかります。 次はさらにsho.javaプログラムを改良してもっと見やすくしていきます。 以下のように変更や追加をしました。 /* Program : sho3.java Student_ID : 045754A Author : Hayato MIYAGI Date : 041122(Mon) Comments : 初級問題の補足 */ import java.util.*; public class sho3{ //sho3.java public static void main(String args[]){ if(args.length != 1){ System.out.println("usage : java sho (The number of trial)"); //実行の仕方の例 System.exit(1); // 異常終了 } long seed = System.currentTimeMillis(); //時間で乱数値を決定 Random random=new Random(seed); //乱数ジェネレータを作成する int A = Integer.parseInt(args[0]); //入力された命令回数をint型に変換 int[] nums=new int[3]; //出力させる数字の個数を3個に指定 int k; for(k = 0; k < A;k++){ //以下のfor文をA回繰り返す for(int i=0; i<nums.length; i++){ nums[i]=random.nextInt(10); //数字をランダムに決定して格納 System.out.print(nums[i]); //決定、格納された数字を出力 } System.out.println(""); //改行させるだけ int B = (100*nums[0])+(10*nums[1])+nums[2]; //Bは3桁の数字を作り出す配列の値を代入 if(B == 777) { System.out.println("FEVER!!"); //"FEVER"と出力して改行 k++; //kの値を1増やす break; //ループ文を抜ける } } System.out.println("trial : "+ k); //実行した回数を出力 if(k == A) System.out.println("trial over!!"); /*指定した回数実行後に"777"がでなければ "trial over"と出力される*/ } } ------------------------------------------------------------------------Result [nw0454:~/prog2/repo4/3] j04054% java sho3 100 345 214 364 824 604 493 186 721 867 . . . 074 644 809 527 528 108 090 015 trial : 100 trial over!! [nw0454:~/prog2/repo4/3] j04054% java sho3 100 018 756 484 681 112 349 727 401 562 . . . . 182 484 705 507 834 883 022 trial : 100 trial over!! [nw0454:~/prog2/repo4/3] j04054% java sho3 100 443 617 076 248 387 916 119 778 . . . 720 345 805 374 364 064 trial : 100 trial over!! [nw0454:~/prog2/repo4/3] j04054% java sho3 100 130 275 510 426 932 786 777 FEVER!! trial : 7 というふうに出力されます。 ここからsho3.javaプログラムの考察をしていきます。 まずは新しく追加した部分の説明からします。以下の部分に注目してください。 import java.util.*; public class sho3{ //sho3.java public static void main(String args[]){ if(args.length != 1){ System.out.println("usage : java sho (The number of trial)"); System.exit(1); } . . . . args[]とはコマンドラインからわたされる引数です。この配列args[]を上記のように if文を用いて表すと、実行コマンドを実行するときに命令を何回実行するのかを自分で 決定することができます。以上のような処理ができれば、命令を1000回でも10000回で も実行することができます。以下に実行の仕方の例をあげておきます。 実行例 [nw0454:~/prog2/repo4/3] j04054% java sho3 100 ^ 命令させる回数を代入するのを忘れずに! 次は public class sho3{ //sho3.java public static void main(String args[]){ if(args.length != 1){ System.out.println("usage : java sho (The number of trial)"); System.exit(1); } long seed = System.currentTimeMillis(); Random random=new Random(seed); int A = Integer.parseInt(args[0]); //入力された命令回数をint型に変換 . . . Integer.parseInt()とは型を変換するためのメソッドです。使う数字をint型で統一するため に使用しました。 次のif文をみてください . . . if(B == 777) { System.out.println("FEVER!!"); //"FEVER"と出力して改行 k++; //kの値を1増やす break; //ループ文を抜ける } . . 上記のif文は配列nums[i]より出力されたint型変数Bのが"777"になったときの制御を 行っています。ここで問題が起こりました。 初め、k++;という一文が不足していたために"777"が出力されたときの実行回数とその 後出力される"trial : (実際に実行した回数)"が1ずれていました。 つまり、"trial : (実際に実行した回数)"のほうが1不足していました。 そこで、"trial : (実際に実行した回数)"が出力される前にKの値を1増加させておけば いいのではないかと思い、k++;をbreak;する前に追加しました。 すると、以下のようにうまく出力させることができました。 [nw0454:~/prog2/repo4/2] j04054% cat -n temp 1 129 2 211 3 931 4 705 5 901 6 161 7 920 8 860 9 491 10 145 11 626 12 850 13 150 14 512 15 639 16 480 17 657 18 127 19 083 20 034 21 897 22 928 23 519 24 926 25 193 26 874 27 520 28 204 29 277 30 294 31 054 32 522 33 434 34 729 35 374 36 640 37 806 38 469 39 136 40 614 41 588 42 570 43 033 44 161 45 188 46 862 47 521 48 777 49 FEVER!! 50 trial : 48 次は実際に命令を実行した回数を超えてしまったときの処理をもう一度 if文を使って行いました。 . . . System.out.println("trial : "+ k); //実行した回数を出力 if(k == A) System.out.println("trial over!!"); /*指定した回数実行後に"777"がでなければ "trial over"と出力される*/ . . . 実行結果を見れば上記のif文が正しく動いていることがわかります。 以上でsho3.javaプログラムの考察を終わります。 以下に上記のJavaプログラムと同様の動作を行うプログラムをC言語 で作成してみました。 /* Program : sho2.java Student_ID : 045754A Author : Hayato MIYAGI Date : 041122(Mon) Comments : 初級問題をC言語で作成 */ #include &stdio.h> //printf()メソッドを使用するために&stdio.h>をインクルード #include <stdlib.h> //random()メソッドを使用するために<stdlib.h>をインクルード #include <time.h> //time()メソッドを使用するために<time.h>をインクルード int main(int argc,char **argv){ // argcには引数の数,argvには引数の文字列が入る if(argc != 2){ //第2引数に何も入力されなかった場合 printf("usage: ./sho2 (The Number of trial)\n"); //実行の仕方の例 return 0; //0の値を返して終了 } long int A = atoi(argv[1]); //第一引数をint型に変換 srand((unsigned int)time(NULL)); //乱数値を時間的に変化させる int B[3]; //配列Bの大きさを宣言 int i,j,k; //int型変数i,j,kを宣言 for(i=0;i&A;++i) //if文の使用 { for(j=0;j&sizeof(B)/sizeof(int);++j) //jの値を3に変換 { B[j]=rand()%10; //出力される数字を0〜9にランダムに決定 printf("%d",B[j]); //決定された数字を出力 } printf("\n"); //改行を入れる k=(100*B[0])+(10*B[1])+B[2]; //3桁の数字を決定 if(k==777){ //"777"が出力された場合 printf("FEVER!! \n"); //"FEVER!!"を出力 i++; //iの値を1増加させる break; //if文を抜ける } } printf("trial : %d\n",i); //"trial : (iの値を出力)" if(i == A){ //"777"が発生しなかった場合 printf("trial over!! \n"); //"trial over!!"を出力 } } 上記のsho2.cプログラムの考察をしていきます。 まずは以下の部分についてこうさつしていきます。 #include &stdio.h> //printf()メソッドを使用するために&stdio.h>をインクルード #include <stdlib.h> //random()メソッドを使用するために<stdlib.h>をインクルード #include <time.h> //time()メソッドを使用するために<time.h>をインクルード C言語ではヘッダファイルをインクルードすることにより 各ヘッダファイルに定義されている標準関数を使用する ことができます。この作業は初めに行わないといけません。 Java言語との違いはC言語は初めにインクルードという作業を 行いますがJava言語ではインポートという作業を行います。 このときインポートするものはJavaではクラスライブラリと 呼ばれるものです。Javaではこのクラスライブラリというものの 中に様々な標準クラスやメソッドが定義されています。 次は long int A = atoi(argv[1]); //第一引数をint型に変換 この一文はatoi();の引数をint型に変換するための一文です。 srand((unsigned int)time(NULL)); //乱数値を時間的に変化させる C言語で乱数を発生させるためにはsrand();を使用します。 for(i=0;i&A;++i) //if文の使用 { for(j=0;j&sizeof(B)/sizeof(int);++j) //jの値を3に変換 { B[j]=rand()%10; //出力される数字を0〜9にランダムに決定 printf("%d",B[j]); //決定された数字を出力 } ここでsizeof(B)/sizeof(int)の動作の説明をします。 配列Bは大きさが3と宣言されていますがint型なので 実際は12バイトになっています。このため、上記の操作 を行わないと実際に実行してみたときに以下のように おかしな結果が得られます。 [nw0454:~/prog2/repo4/2] j04054% ./sho2 5 7568183120022 4493193693843984140096 1601419163958898238401940744166901 trial : 8 となってしまい、コマンドラインで指定した命令実行回数と 実際に実行した回数(trial)の数が合っていません。 sizeof(B)/sizeof(int)の処理を行うことによって配列Bの大きさ を3に指定することができます。 ここであまり触れなかった部分についての説明をします。 Java言語とC言語。この両者には似通った表現がたくさん存在します。 例えば、標準出力を行うものでは、 Java--------System.out.print(); C --------printf(); のように似たもの同士が結構います。 よって、個人的に似たもの同士の説明は省かせていただきました。 以上で考察を終わります。 5.反省と感想 今回のレポートは作成に時間がかかってしまいました。初級問題を 作成しようといろいろな問題(かけ算九九など)を考えましたが、やはり 少し面白いものを作成しようと思い、今回のスロットプログラムを 作成しました。問題はどうすれば乱数をうまく発生させることができる のかと試行錯誤を重ねました。プログラムが完成したときはうれしかった です。 最後にこのスロットプログラムを何回も実行して気がついたのですが、 横一列に777を出力させるためには平均的に約800〜1000回くらい実行 しなければなりません。これより予想できることはカジノに行ってFEVER するためには、一ゲームあたり50円としてFEVERを出すためには4〜5万円 も浪費してしまうという結果が得られます。さらに縦、横、斜めに777が 揃えるためには最低でも800*800*800=???00000,回実行というとんでも ない数字が出てきてしまいます!こんなスロットを回すお金があるなら もっと他のことにお金を使ったほうがイイと思いました。私にはギャンブル にはまる人たちの気持ちがわかりません。怖いです。 6.参考文献 独習Java第2版 ジョセフ.オニール 著 トップスタジオ 訳 武藤 健志 監修 C実践プログラミング Steve Oualline 著 望月 康司 監修 谷口 功 約