【Java】プログラムの読み方は初心者でも分かる?素数判定のコード解説と動作確認

このQ&Aのポイント
  • Javaの学習を始めて数週間の初心者です。条件分岐、ループ、配列、メソッドを使用したプログラムを作成する課題に取り組んでいます。素数を判定するプログラムを作成しましたが、コードの動作や処理の流れについて理解が不十分です。
  • 質問の内容として、(1)2つ目のfor文でsumが2の場合の処理の流れ、(2)2つ目のif文でfalseになった場合の処理の流れ、(3)breakの後の処理の流れ、についての説明を求めています。具体的な処理の流れを教えていただけると助かります。
  • 初心者の私がわからない部分として、if文やfor文の入れ子のブロックで処理がどのように移っていくかが不明瞭です。これらのケースにおける具体的な処理の流れと理由について、アドバイスをいただけると嬉しいです。
回答を見る
  • ベストアンサー

【Java】プログラムの読み方

Javaの学習を始めて数週間の初心者です。 皆さんのお知恵を貸してください。 条件分岐、ループ、配列、メソッドを使用したプログラムを作成する、 という課題です。習っただけでなく自分でちゃんと使えるか、という意図だと思います。 素数を判定するプログラムにしようと考えました(もっと単純なもので構わないのですが、思いつかなかった…)。 ネットを検索して考え方を参考にしながら、書いてみました(コピペではないです)。 不細工で読みにくいかもしれませんがよろしくお願いします。 概要(問題のソースは最下部) ・キーボードで3つの数字を入力し、それらを配列numに代入する(readLine使用)。[メソッド][配列] ・(ここからペーストしたソース)配列をfor文で足し込み合計値をsumに代入。[ループ] ・2以上とそれ以外に分ける(素数は2~)。[条件分岐] ・2以上、sum未満の数で順番に割っていく。 ・1回でも割り切れたらboolean型sosuにfalseを代入、処理を終了させる。 (ここには載っていませんが、sosuはtrueで初期化済み) ・sosuがtrueかfalseかで表示を変える。 とりあえずソースを書いてコンパイルも通り、実行した結果も一応私の意図通りに動きます。。 が、これを講師の方に動きを説明しないといけません。一つ一つの動きは理解できるのですが、 ifの入れ子のブロックで処理がどう移っていくのかが不明瞭です。 お訊きしたいのは以下のケースで処理がどう動くのか、です。理由もお願いします。 (1)2つ目のfor文、1回目でfalseの場合(例えばsumが2の時) …2の場合、「素数です」と表示されますが、改めて読むと「elseに飛んでsosu = falseになるのでは?」 という疑問があります。具体的な内容を伏せて講師の方に訊いてみると「上のif文でtrueになっても その下のfor文でfalseならばelseに飛ぶはず」と言われました。 (2)2つ目のif文、falseになった場合 …この場合、falseなら素数と判定された、と思っていて実行結果もそのようになるのですが、 「elseに飛ぶ、が正しいならおかしくないかな?」と感じます。 (3)breakの後 …大体上と同じ疑問です。 (4)要は入れ子になっている場合、どこに処理が移るかがちゃんと解っていないのだと思います。 このような場合の読み方のアドバイスをお願いします。 情報に不足があればご指摘ください。 ↓ここからソース↓ (略) System.out.println("※合計値はint型の範囲内になるよう注意してください。"); (略) int sum = 0; for (int i = 0; i < num.length; i++) { sum += num[i]; } if (sum >= 2) { for (int i = 2; i < sum; i++) { if (sum % i == 0) { sosu = false; break; } } } else { sosu = false; } if (sosu == true) { System.out.println("\n合計値" + sum + "は素数です。"); } else { System.out.println("\n合計値" + sum + "は素数ではありません。"); } (以下略)

  • Java
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.3

> 「上のif文でtrueになってもその下のfor文でfalseならば > elseに飛ぶはず」これは正しいでしょうか? いいえ,間違っています。 -------- 01 if (sum >= 2) { 02 ■ for (int i = 2; i < sum; i++) { 03 ■● if (sum % i == 0) { 04 ■●★ sosu = false; 05 ■●★ break; 06 ■● } 07 ■ } 08 } else { 09 □ sosu = false; 10 } -------- 上記のコードにおいて, 01行目の if (sum >= 2) { が真のときに実行される■のブロックと, それが偽のときに実行される 08行目 else { 以降の□のブロックは, 二者択一の関係にあります。 02行目,03行目,05行目が実行されたとしても それらはすべて■ブロック内にある命令ですから, □ブロックに実行が移ることはありません。 ちなみに, 05行目の break は,もっとも内側にあるループ(今回は,02行~07行のforブロック)に作用する命令であり,このループから脱出するという機能を実現しています。 したがって, 「05行目 break; の実行」→「forループを脱出して 07行目の次に移動」→「08行目の }で ■ブロックの実行もすべて終了」→「(if{} else{}の固まりの外にある)10行目の次の命令に移動」という実行の流れになります。 ---------------- > if (sum >= 2) { // sumが2ならここはtrueですよね。 > for (int i = 2; i < sum; i++) { > // iを2で初期化するので2 < 2となりfalseである > と理解するのは間違いでしょうか? そこまでの理解は正しいです。 回答No.1は次のことを指摘しているわけです。 「この場合のループ継続条件 2 < 2 はfalseなので,●で示されたforブロックの内部は一度も実行されない。前述の理由で □ブロックに実行が移ることもない。つまり,sum=2 の場合は 04行目も09行目も実行されないから,質問文に提示されていない「(略)」の箇所のコードで設定されたsosuの値がそのまま適用される」

lucky_life
質問者

お礼

お礼をしたつもりができていませんでした…大変失礼致しました! 遅くなりましたが、 ■●★を使った視覚的な説明は大変解りやすく納得出来ました。 これからも頑張って学習を進めて行きたいと思います。 ありがとうございました。

その他の回答 (2)

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.2

変数の値を追いかけて、このプログラムのルートを全て通るにはどのような変数の値をとれば良いかを考えます。 影響を与えるのはsumだと考えます(readLineによる入力はどうとでもできるので)。 このプログラムでは、 sumが0以下の場合 sumが1の場合 sumが2の場合 sumが3以上の場合 で動作が異なると考えられます。 >iを2で初期化するので2 < 2となりfalseであると理解するのは間違いでしょうか? falseとなり、forブロックは実行されません。 forブロックは実行されないので、変数sosuがfalseになる機会がなく、変数sosuの初期値がtrueなので、sum==2の場合は「合計値 2 は素数です。」という結果が得られています。 >…2の場合、「素数です」と表示されますが、改めて読むと「elseに飛んでsosu = falseになるのでは?」 飛ぶと思われるelseブロックにSystem.out.printlnを挿入して、実際にsum==2として実行してみると良いと思います。 >その下のfor文でfalseならばelseに飛ぶはず この文だけを読む限りは飛びません。if~elseとforの判定処理は独立しているからです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

入れ子になってるならどう対応するのかを考えなきゃならない. マーカーなりボールペンなりで対応関係に色を付けてみたら? あと, (1) で sum が 2 だと「2つ目のfor文、1回目でfalseの場合」には当てはまらないよ.

lucky_life
質問者

お礼

ご回答ありがとうございました。 皆さんのアドバイスを総合するとより理解が深まりました。 これからは対応関係を常に意識するように心がけたいと思います。

lucky_life
質問者

補足

ご回答ありがとうございます。 > (1) で sum が 2 だと「2つ目のfor文、1回目でfalseの場合」には当てはまらないよ. あれ、そうなのですか…? if (sum >= 2) {           // sumが2ならここはtrueですよね。  for (int i = 2; i < sum; i++) {  // iを2で初期化するので2 < 2となりfalseであると理解するのは間違いでしょうか? もしかして私基本的な勘違いしてたりするのかな。 ソースとテキストfor文の箇所を見返していますがわからない…。 自分のプログラムなのに混乱してきました(笑)。もう少し考えます。 後、「上のif文でtrueになってもその下のfor文でfalseならばelseに飛ぶはず」 これは正しいでしょうか? ※投稿した後でソースのTabインデントが無効になっているのに気付き、 (私が)読みにくいので、スペースで下げます(内容は同一)。 (略) System.out.println("※合計値はint型の範囲内になるよう注意してください。"); (略) int sum = 0; for (int i = 0; i < num.length; i++) {  sum += num[i]; } if (sum >= 2) {  for (int i = 2; i < sum; i++) {   if (sum % i == 0) {    sosu = false;    break;   }  } } else {  sosu = false; } if (sosu == true) {  System.out.println("\n合計値" + sum + "は素数です。"); } else {  System.out.println("\n合計値" + sum + "は素数ではありません。"); } (以下略)

関連するQ&A

  • 【Java】ある数列から、素数を探すプログラムについて

    Java初心者です。独学なので質問できる環境が無く、 こちらで質問致します。回答をお願い致します。 以下のプログラムについて質問です。 class Prime { public static void main(String[] args) { int max = 100; // 素数を探す数の最大値 boolean[] a = new boolean[max]; // 素数かどうか判定する配列 // 配列の初期化 for(int i = 0; i < max; i++) a[i] = true; // 素数かどうか判定 for(int i = 2; i < max; i++) { if(a[i-1]) { for(int j = 2; i*j <= max; j++) a[i * j - 1] = false; } else continue; } // 結果を表示 for(int i = 1; i < max; i++) { if(a[i]) System.out.print((i + 1) + " "); } System.out.println(); } } 上記の「配列の初期化」の個所、 for(int i = 0; i < max; i++) a[i] = true; ここでなぜ、a[i] = true;となるかわかりません。 0と1はどちらも素数ではないと思うので、 私はtrueではないと思うのですが・・・。 ぜひとも教えて頂きたいと思います。

    • ベストアンサー
    • Java
  • javaで素数を探すプログラム。

    javaで素数を探すプログラム。 初歩的なことかと思いますが、助言をお願いします。 if(a[i-1]) ←この部分がわかりません。これはどのような条件がなのでしょうか? class Prime { public static void main(String[] args) { int max = 100; // 素数を探す数の最大値 boolean[] a = new boolean[max]; // 素数かどうか判定する配列 // 配列の初期化 for(int i = 0; i < max; i++) a[i] = true; // 素数かどうか判定 for(int i = 2; i < max; i++) { if(a[i-1]) { for(int j = 2; i*j <= max; j++) a[i * j - 1] = false; } else continue; } // 結果を表示 for(int i = 1; i < max; i++) { if(a[i]) System.out.print((i + 1) + " "); } System.out.println(); } } このプログラム

    • ベストアンサー
    • Java
  • Java初心者です。どうか教えてください><

    1週間ほど前からJavaの勉強を始めたものです。初歩的な質問で申し訳ないのですが、是非おしえていただきたくて投稿いたしました。 秀和システムからでている「わかりやすいJava入門編」を使って勉強しているのですが、課題の1つでつまづいてしまい、解決法がわからないので質問させていただきました。 課題の内容は以下です。 1、10本のうち3本が当たりで、最大10回引ける。あたりが出たら取り出す。3つ全てあたりが出たら終了。 2、eclipseのコンソール画面上から「キーをタイプすればくじが引けます」と表示、キーを入力すればくじ引き開始。 3、キー入力後0.1秒ごとに ■ が表示され、1秒後10個になった時点でくじ引き結果表示。 そこで、わたしは、まずint[ ]の配列を10個用意し、ループ分で[0]~[9]まで順にランダムに0~9の数字を入力し、 i番目の[i]に入っている数字が、それより以前の配列に入っている場合、[i]配列の抽選をやりなおす、というやり方でやろうと思って以下のような書き方をしたのですが、どうやら間違っているようで重複の場合のやり直しをしてくれません;; 初心者なので、見づらい書き方をしているかもしれませんがお許しください>< package exercise; import lib.Input; public class Lot_6 { static int[] lot = new int[10]; static int i; public static void main(String args[]){ int a = 0; for(int i=0; i < lot.length ;i++){ if (a < 3){ Input.getString("キーをタイプするくじが引けます"); animation(); do{ lot[i]=(int)(10*Math.random()); } while(isTrue()); if((lot[i] == 0) ^ (lot[i] == 1) ^ (lot[i] == 2)){ System.out.println("あたり"); a++; } else { System.out.println("はずれ"); } } else { break; } } } public static void animation() { for(int m = 0;m < 10;m++){ System.out.print("■ "); delay(100); } } public static void delay(int t) { try { Thread.sleep(t); } catch (InterruptedException e) { e.printStackTrace(); } } public static boolean isTrue(){ boolean is = false; for(int n=0;n <= i-1;n++){ if(lot[i] == lot[n]) is = true; else { continue; } } return is; } } そこで、間違っている箇所を調べるために do{ } while();ループの中にSystem.out.println(isTrue());を加え、if(a < 3) { }の内の最後にSystm.out.println(lot[i]);を加えました。 ちゃんと重複した場合isTrue()にTrueを返しているか、重複した場合やりなおしをしてくれているか、を調べるためです。 そしてコンソール画面の実行結果が以下です。 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 6 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 3 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false あたり 1 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 4 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false あたり 0 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 4 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 4 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 5 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false はずれ 9 [キーをタイプするくじが引けます] > ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ false あたり 2 数字が重複していますし、trueが一個もありません。 ということはisTrue()メソッドの部分で誤りがあるんでしょうか? public static boolean isTrue(){ boolean is = false; for(int n=0;n <= i-1;n++){ if(lot[i] == lot[n]) is = true; else { continue; } } return is; } こう書けば、lot[i]がlot[0]~lot[i-1]の間でいつでも重複しているものがあれば boolean is = true;により上書きされて、isTrue()はtrueが返されると思ったのですがそうはならないのでしょうか。 すいません。いろいろ手は尽くしたのですがどうしても分からなくて質問させていただきました。 ご回答いただけますとうれしいです><b

  • Java for文

    for文について、キーボードで入力して、その数が素数(1またはその数以外で割り切れない数)であるかを判断するコードですが、for文とif文の関係が良くわかりません。ご教示ください。 <サンプル> public static void main(String[] args) throws IOException{ System.out.println("2以上の整数を入力してください。"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str = br.readLine(); int num = Integer.parseInt(str); ※1 for(int i=2; i<=num; i++){ if(i == num){ System.out.println(num + "は素数です。"); ※2 }else if(num % i == 0){ System.out.println(num + "は素数ではありません。"); break; ※1と※2の処理について初心者でもわかるような解説をおねがいできますでしょうか? よろしくお願いいたします。

  • プログラムのスレッド化について。

    以下の処理をスレッド化しようとしています。 public class FCP{ int N=10 long LOOP_MAX=100 double x[][] = new double[N][4] int g[][] = new int[N][4] boolean y[][] = new boolean[N][4]//出力 boolean A[][] = new boolean[N][10] double T=0.5 Set_Adjacent_Matrix() //A配列にtrueとfalseを代入 Set_initial_value() //y配列に初期値を代入(Math.random()>0.5) g1(int i, int j) //k<4 sum=1 if( y[i][k] == true ) --sum return(double)sum g2(int i, int j) //k<N sum=0 if( y[i][j] == true ) if( y[k][j] == true && A[i][k] == true ) --sum return(double)sum Display_output() //結果表示 if( y[i][j] ) System.out.print("0") else System.out.print(".") public static void main(String args[]) { long loop; int i, j, k; Set_Adjacent_Matrix(); Set_initial_value(); for( loop=0; loop<LOOP_MAX; loop++ ){ for( i=0; i<N; i++ ){ for( j=0; j<4; j++ ){ x[i][j] = g1( i, j ) + g2( i, j ); if( y[i][j] ){ x[i][j] += T; }else{ x[i][j] -= T; } if( x[i][j] > 0.0){ y[i][j] = true; }else{ y[i][j] = false; } } } Display_output(); } } 今回Threadクラスの継承を使ってスレッド化しようと考えました。runメソッドには上のプログラムのmain部分の処理をさせようと思っています。そしてstartメソッドで必要な数(Nの値=10コ)のスレッドを生成しrunメソッドを実行する。 と、ここまではわかったのですが、「生成された各スレッドの番号を保持し、そのスレッドに担当させる処理を決める」という部分をどうすればいいのかわかりません。 「i(1~10)番目のスレッドはN(1~10)列目の処理を担当している」という風にするにはどうしたらいいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • continue文以外で・・・

    以下はcontinue文を使用したソース片なのですが、このソースをcontinue文以外の方法で表現することは出来るのでしょうか? もし他にも表現方法があれば、教えていただきたいのですが・・・。 int[] score = {71, 90, 10, 84, -7, 99}; int sum = 0; for (int i=0; i<score.length; i++){ if (score[i] < 0){ continue; } sum += score[i]; } System.out.println("合計は" + sum "です。");

    • ベストアンサー
    • Java
  • 【Java】複数の引数の数値と文字列の判定

    Javaについてです。 コマンドライン引数を複数渡し、渡ってきた値が数字のみの場合は、数値*数値の文字数を出力し 数字のみでない場合は文字列を逆から1文字ずつ出力する。 数値の判定はtry/catchで行い、catchメソッドには「stringFlg = true;」のみにする。 というプログラムを作りたいのですが、 引数が1つの時は上手くいくのですが、11 2あ あ3 44を渡した場合、 22 あ 2 3 あ 88 と出るはずが、 22 1 1 あ 2 3 あ 4 4 と出てしまいます…。 どうしたら全ての引数を正しく表示出来るのでしょうか?教えて下さい。 現時点のソースコードです。 public class Test { public static void main(String[] args) { boolean stringFlg = false; try { if(StringUtils.isNumeric(args[0])){ for(String arg : args) { int num = Integer.parseInt(arg); System.out.println(num * arg.length()); } } else{ stringFlg = true; } } catch (NumberFormatException e) { stringFlg = true; } if(stringFlg){ for(String val : args) { String[] str = val.split(""); for(int i = str.length-1; i >= 0; i--){ System.out.println(str[i]); } } } } }

    • ベストアンサー
    • Java
  • プログラムの平均値の出し方。

    プログラムの平均値の出し方。 public class pazu{ public static void main(String[] args){ int sum =0,saidai; System.out.println("コマンドラインパラメータは"+args.length+"個です"); for(int i=0;i<args.length;i++){ int x=Integer.parseInt(args[i]); if(pazu.is_even(x)) System.out.println(args[i]+"は偶数です"); else System.out.println(args[i]+"は奇数です"); sum+=x; } saidai=pazu.max(args); System.out.println("合計:"+sum); System.out.println("最大:"+saidai); } static boolean is_even(int number){ return number%2==0; } static int max(String[] number){ int max =0; for(int i=0;i<number.length;i++){ if(max<Integer.parseInt(number[i])){ max=Integer.parseInt(number[i]); } } return max; } } このプログラムで数値の奇遇、合計値、最大値までは出せたのですが平均値の出し方がわかりません。 どこに何を入れればいいかを教えてください。お願いします。

  • for文を使った累乗の計算方法について

    質問させてください。 for文を使った累乗の計算プログラムを作っています。 数値はコマンドライン引数から取得し、0番目の数字を i番目の数字分累乗するというものです。 ソースを途中まで作成したのですが、0乗した場合のプログラムが よく分かりません。どなたか教えていただけないでしょうか? public class Mondai { public static void main(String[] args) { //変数の初期化 int k = 0; if ( 2 <= args.length && args.length < 3) { //コマンドライン引数の数だけ配列を用意する int[] num = new int[args.length]; //0,1番目のコマンドライン引数を整数に変換してnumに代入する num[0] = Integer.parseInt(args[0]); k = num[0]; k *= k; num[1] = Integer.parseInt(args[1]); //num[1]の掛け算をnum[1]回繰り返す for (int i = 0; i < num[1] -2; i++) { k *= num[0]; } System.out.println("\"" + num[0] +"の" + num[1] + "乗は"+ k + "\""); if(num[1] == 0) { System.out.println("\"" + num[0] +"の" + num[1] + "乗は1\""); } //args.length <= 1の条件の時 } else if(args.length <= 1) { System.out.println("引数が足りないため累乗の計算ができません。"); //指定された条件以外の時 } else { System.out.println("引数が多すぎるため累乗の計算ができません。"); } } }

    • ベストアンサー
    • Java
  • このプログラムにアドバイスをください

    問題が  ・100個の要素を持った一次元配列をmain()関数内で宣言 ・一次元配列と要素数を引数として持つ関数seisei() ・関数seisei()は乱数を使い渡された配列を0~99の整数で初期化する。 ・一次元配列、要素数そして変数のポインタを引数としてもつ関数goukei() ・関数goukei()は渡された配列に格納された数値の合計を計算し、渡された変数のポインタにその合計値を代入する。 と問題があり、下記のようにプログラムを作ったんですが、どうしてもコンパイルできません。どなたかご指摘よろしくお願いします。 #include <stdio.h> #include <time.h> void seisei(int *,int); void goukei(int *, int, int*); int i, *sum; int main() { int a[100],sum; seisei(a,100); goukei(a,100,&sum); printf("sum:%d\n",&sum); return 0; } void seisei(int *a[i], int n) { srand(time(NULL)); for(i = 0; i <= n; i++){ *a[i] = rand() % 100; } } void goukei(int *a[i],int n,int *sum) { *sum = 0; for(i = 0; i <= n; i++){ *sum += *a[i]; } }

専門家に質問してみよう