質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.45%

  • Java

    16214questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1970questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

2以上の数値で素因数分解を求めるプログラム

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 6,067

yoppi07

score 21

このソースコードは変数xが入力された値を格納しint型のyへ渡しているという認識です。
初歩的な質問かもしれませんが、なぜforの中でさらにwhileで繰り返す必要があるのかわかりません。
for、whileの中のコードの理解が出来ていないです。
そもそも、繰り返し処理を記述しなければいけないのでしょうか?
条件分岐でもこのプログラムは実現出来る気がするのですが、解説お願いします。

該当のソースコード

    public static void main(String[] args) {

        System.out.println("数値を入力して下さい");
        Scanner num = new Scanner(System.in);
        int x = num.nextInt();
        int y = x;

        for (int i = 2; x > i; i++) {
            while ((y % i) == 0) {
                System.out.println(i);
                y = y / i;
            }
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

ループの中で何をしているのか

for、whileの中のコードの理解が出来ていないです。

((y % i) == 0)という条件式で、何をコントロールしているのかじっくり考えてください。

ループの中にループがある理由

なぜforの中でさらにwhileで繰り返す必要があるのかわかりません。

『ループが入れ子になっている』『ネストしている』という表現をします。

元のプログラムでループが入れ子になっているのは、二回以上用いられる約数のためです。
内部のループを外すと、24 = 1*2*2*2*3が計算できません。

そもそも

二重ループにしているのは無駄だと思います。以下で充分。

int i = 2;
while(y != 1) {
    if(y % i == 0) {
        System.out.println(i);
        y /= i;
    }
    else {
        i++;
    }
}

繰り返しは必要か

そもそも、繰り返し処理を記述しなければいけないのでしょうか?

再帰処理を用いれば実現可能です。(ただし、非推奨)

private void recursionPrime(int arg, int div) {
    if(arg == 1) return;

    if(arg % div == 0) {
        System.out.println(div);
        recursionPrime(arg/div, div);
    }
    else {
        recurtionPrime(arg, div+1);
    }
}
private void printPrimeFactor(int arg) {
    recursionPrime(arg, 2);
}

なんか、Javaっぽくないプログラムになってしまいました...
raccyさんの指摘のとおり、Javaでの安易な再帰処理の使用は推奨されません。
特に拘りや制約条件のない限り、ループで処理するのがよいでしょう。

重要

コードはバッククオート三つで括ってください。
よくわからない場合は、マークダウン記法について調べてみてください。
これをしているかどうかで、回答の量と質が変わってきます。
(マークダウン記法を用いていない質問者には回答しない、という方針の人もいます。)

追記

anahina1979さんが、以下のとおり驚くべき真実を教えてくださいました。

ちなみに、素数は2以外の偶数は存在しない

それを反映するとこうなります。

while(y % 2 == 0) {
    System.out.println(2);
    y /= 2;
}

i = 3;
while(y != 1) {
    if(y % i == 0) {
          System.out.println(i);
           y /= i;
    }
    else {
           i+=2;
    }
}

処理速度が上がって、オーダーで言うとO(n)からO(n)になりましたね!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/04 18:13

    ずいぶん原型なくなっちゃいましたが(w
    これなら、y使わないで直接xを除算でよいですね。

    キャンセル

  • 2017/08/04 18:16

    『とりあえずfor文使っとけ』という風潮が問題な気もします。
    どちらかと言うとwhile文の方が汎用性が高いと思うのですが...

    おっしゃるとおり、yの存在意義はもはやないです。

    キャンセル

  • 2017/08/04 21:19

    ちなみに、

    素数は2以外の偶数は存在しない

    キャンセル

  • 2017/08/04 21:24

    実行速度とスマートさどっちを取るかだと思いますね。
    最初だけ分岐すると、ちょっと汚くなるように感じるのです。

    キャンセル

  • 2017/08/04 22:29

    Javaは末尾再帰最適化をサポートしていないため、素因数が大きめの数字ではスタックオーバーフローで止まってしまうのではないでしょうか?再帰回数がそれなりに少ないことがわかっていないなら、Javaで再帰関数は使うべき(勧めるべき)では無いと思われますが、いかがですか?(私としては、そもそもJavaを勧めないんですけど)

    キャンセル

  • 2017/08/04 22:42

    質問の『そもそも、繰り返し処理を記述しなければいけないのでしょうか?』という記述に対する返答であって、勧める意思はないです。
    誤解のないよう、非推奨であることを追記させていただきますね。

    キャンセル

  • 2017/08/04 22:43

    raccyさんの質問/回答/コメントではいつも勉強させていただいています。
    コメントありがとうございます。

    キャンセル

checkベストアンサー

0

実際に紙面上で素因数分解しながら読んでください。例えば540の素因数分解を考えます。

  1. まず一番小さな素数"2"で割れるか試します(for文でi=2)。
  2. その素数で割れるだけ割ります(while(y%i==0))。
    540/2=270,270/2=135,135は2で割れない
  3. 次の素数"3"で割れるか試します(forの更新文i++)。
  4. その素数で割れるだけ割ります(while(y%i==0))。
    135/3=45,45/3=15,15/3=5,5は3で割れない
  5. 次の素数"5"で割れるか試します。
    正確にはいったんiは4になりますが、前のステップで2で割れるだけ割っているため、
    4では絶対割り切れないのでwhile文に入れず次のforに入る。
  6. その素数で割れるだけ割ります(while(y%i==0))。
    5/5=1

という行程を踏むループになっています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

なぜforの中でさらにwhileで繰り返す必要があるのかわかりません。

whileは置いといて、for文からですが、素因数を求める為に、割り算に使う i を2から
自分の数字の1つ前までのループさせれば良しとしています。もれは無いでしょう。
なのでfor (int i = 2; x > i; i++){ .... }

さらにプログラムは素因数分解を求める為に、whileを使っているいます。
(整数が、どんな数であっても、素数の積によって表すことができる)

素因数分解を行うには、順に小さいものから割りまくるです。
割り算する数字が同じでも、割り切れている内は何回でも割ります。yは減っていきますけど。
例えば 20 の場合2,2,5になります。(構成しているのは素数です。)

これをwhileで実現しています、(割り切れている間は回る)
実際20の場合、割切れる2は2回ループして
y、が5になった時点で2では割り切れず、forループへ移ります。y/i は次の次の次の5で割り切れます。
forループは5から先の19までループして終了します。ちょっとだけ効率化するとして yが1になった時点で
forループをberakすれば良いかな。

入力が素数の場合でもforループの回数は入力数の半分で良いのですけれどね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.45%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    16214questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1970questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。