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

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

ただいまの
回答率

88.76%

素数を求めるジェネレーター

受付中

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 1,108

newyee

score 155

以下は素数を求めるためのコードとなるのですが、お聞きしたい所がございます。

//素数を求めるためのジェネレーター
function* genPrimes() {
  let num = 2;//素数の開始位置
//2から順に素数を判定し、素数の場合にだけyield(無限ループ)
  while (true) {
    if (isPrime(num)) { yield num; }
    num++;
  }
}
//引数valueが素数かどうかを判定
function isPrime(value) {
  let prime = true;//素数かどうかを表すフラグ
//2~Math.sqrt(value)で、valueを割り切れる値があるかを判定
  for (let i = 2; i <= Math.floor(Math.sqrt(value)); i++) {
    if (value % i === 0) {
      prime = false;//割り切れたら素数ではない
      break;
    }
  }
  return prime;
}



for(let value of genPrimes()) {
//素数が101以上になったら終了
  if (value > 100) { break; }
  //console.log(value);

}


上記、while文内の「if(isPrime(num))」この部分のnumの値が2から順当に加算されていき「4」が入った時の、処理に関してなのですが、まず、isPrime関数のfor文の条件式がTRUEとなり、次のif文内で、primeがfalseとなり、if文を抜け、for文の繰り返しに戻り、iの値が3となり条件式がfalseとなり、return prime が実行され、while文に戻ります。次にnumの値が、5となりisPrime関数が実行され、primeにtrueが入り、for文が実行されるのですが、この時、iの値が2のままだと、primeの値がfalseとなってしまいます。iの値が、numの値が4だった時の3のまま継続されるということはないと思うのですが、このままだと素数であるはずの5が返らないということになってしまいます。
この点に関しまして、どうしても理解できないため、ご解説の方お願いしたいです。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • yukke_

    2018/09/15 18:50

    すみませんが、ごちゃごちゃ書かれてて何を聞きたいのか分かりません。もう少し整理してもらえますか?

    キャンセル

回答 4

+3

この時、iの値が2のままだと、primeの値がfalseとなってしまいます。

なりません。5は2で割り切れません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/15 19:30

    あ、代入されているわけではないので、変化しないということだったんですね...
    基本的なことが分かってなかったです...
    しかし、「 i=Math.floor(Math.sqrt(value));」ではなく、「i <= Math.floor(Math.sqrt(value))」となっており、代入されている訳ではないという所で、「i <= Math.floor(Math.sqrt(value))」ここの部分の条件式が何を意味しているのかがいまいち分からないんですよね...

    キャンセル

  • 2018/09/15 19:44 編集

    簡単に書くと「i * i <= value」ということです。
    たとえばnum=11で考えると、3*3=9、4*4=16なので「i=3」まで計算するという形ですが、
    11まで素数を探すときは2*[2,3,4,5]、3*[2,3]という形で、4以降は2、3の時の組み合わせを繰り返すだけなので平方根以下、というくくりなのです。
    …小難しくなった@@;

    キャンセル

  • 2018/09/15 19:50

    ご解説ありがとうございます。
    自分の理解が悪いため、完全とにではないのですが、おおまかに理解できた気がします!

    キャンセル

+1

動かしてみましたが問題なかったです。
「2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97」
が選択されましたよ。

 追記

素数計算
提示のソースそのままで表示部のみ追加した形です。
リンククリックすると97まで素数を表示しますよ。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

//value % i
5%2=1


ですよ……

ちなみに、for (let i = 2; i <= Math.floor(Math.sqrt(value)); i++) の部分はこのループに入る際に let i = 2 で i を初期化しているため、次回の isPrime() 呼び出しで値が引き継がれることはありません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/15 20:43

    ご回答頂いた部分でどうしてもお聞きしたいことがあるのですが、「for (let i = 2; i <= Math.floor(Math.sqrt(value)); i++)」この部分の、「i <= Math.floor(Math.sqrt(value));」ここの条件式において、「Math.floor(Math.sqrt(value))」ここの「value」の値は、Math.sqrt及びMath.floor関数によって、変化していると思っていたのですが、他の方からもご指摘を受けたのですが、変化していないとのことでした。
    そうなりますと、仮に、valueの値が5だった場合、条件式の中で「Math.floor(Math.sqrt(value))」ここの部分に2つの関数を通す意味はなんなのでしょうか?valueの値が変化していないのだとしたら、関数を通すいみはないように思えてしまうんですよね...

    キャンセル

+1

理解なさったようですが、どうしても気になるので。

まず、isPrime関数のfor文の条件式がTRUEとなり、次のif文内で、primeがfalseとなり、if文を抜け、for文の繰り返しに戻り、iの値が3となり条件式がfalseとなり、return prime が実行され、while文に戻ります。

ここのところ明らかに間違っています。breakのことを考えておられません。
「isPrime関数のfor文の条件式がTRUEとなり、次のif文内で、primeがfalseとなり、if文を抜け、」とのことですが、primeがfalseになる次の行でbreakが起こり、forを抜け、直ちにreturn false;となります。iは3にはなりません。

-- 蛇足

条件式の中で「Math.floor(Math.sqrt(value))」ここの部分に2つの関数を通す意味はなんなのでしょうか?valueの値が変化していないのだとしたら、関数を通すいみはないように思えてしまうんですよね

条件判定のために、関数にかけています。またvalueを変えないままiがvalueの平方根を切り捨てした値以下であるか比較するために、わざとvalueを変化させずに比較しているのです。

しかしながら

function isPrime(value) {
//2~Math.sqrt(value)で、valueを割り切れる値があるかを判定
  let ceiling = Math.floor(Math.sqrt(value));
  for (let i = 2; i <= ceiling; i++) {
    if (value % i === 0) {
      return false;
    }
  }
  return true;
}


というように一旦他の変数(ceiling)に受けることは可能なので、「なんでこうなっているか」は、究極的にはこのコードを書いた人に聞くしかないでしょうね。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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