素数計算サイト2

完成編

 

素数計算処理をつくる

  • では、必要な知識がそろった所で、素数計算の処理を書いていきましょう。もちろんJSファイルに書きます。
  • まずは変数を作っている部分からです。下のコードをみてください。
  • 変数start(スタート)変数end(エンド)に関しては、フォームに入力された"文字"を数字に変換して、それぞれの変数に代入してましたね?
  • 3行目の【 var kotae = [];】は空の配列を作っているところです。
    • 後から、この配列に素数を入れていく感じです。
function prime() {
  var start = parseInt(document.formPrime.start.value,10);
  var end = parseInt(document.formPrime.end.value,10);
  var kotae = [];
}

JSファイル

while (start <= end) {
    var check = 2;
    var isPrime = true;
    while (check < start) {
        if (start % check === 0) {
            isPrime = false;
        }
        check++;
    }
    if (isPrime) {
        kotae.push(start);
    }
    start++;
}

JSファイル

素数計算処理をつくる

  • 次は今回の主役、素数を判定している処理です。

    • まだ理解するには難しいとは思いますが、細かく説明していきますますので、少しでも理解できるようがんばりましょう

  • while(ホワイル)がネスト(2重)になっています。

  • 外側(1つ目)のwhileから見ていくと、【while (start <= end) 】で、”開始値”から”終わり値”までを、くり返す文だというのがわかります。

JSファイル

素数計算処理をつくる

  • 次に素数かどうかを割って判定(はんてい)する用に変数checkを作っています。

  • このcheck2からスタートし、2つ目のwhileの中で、1づつ値を増やしながら、startの数値の1つ前まで、割り切れるか(余りが0になるか)を知らべています。

while (start <= end) {
    var check = 2;
    var isPrime = true;
    while (check < start) {
        if (start % check === 0) {
            isPrime = false;
        }
        check++;
    }
    if (isPrime) {
        kotae.push(start);
    }
    start++;
}

JSファイル

素数計算処理をつくる

  • 次に、checkで割った数が、「素数」(true)か「素数ではない」(false)かを保存する変数isPrimeを作っています。

  • このisPrimeは最初はtrueを代入しているので、もしcheckで割り切れる数が見つからなかったときはそのままtrueになりますが、途中でcheckが「割り切れる数(素数ではない)」を見つけると、falseに変更されるようになっています。

  • 素数は【1か、自分自身の数以外では、絶対に割り切れない】数のことなので、割り切れたら【素数ではない】ため、false(フォルス)を代入します。

while (start <= end) {
    var check = 2;
    var isPrime = true;
    while (check < start) {
        if (start % check === 0) {
            isPrime = false;
        }
        check++;
    }
    if (isPrime) {
        kotae.push(start);
    }
    start++;
}

JSファイル

素数計算処理をつくる

  • そして内側(2つ目)のwhile(ほわいる)が終わるごとに、isPrimetrue(トゥルー)のままであれば、その数(start)が配列kotaeに追加されるようにしています。false(フォルス)場合は何もしません。
  • その後、start1増やしてから、外側(1つ目)のwhileの最初に戻って、2週目が開始されます。
  • この流れを、”終わり値”の数まで繰り返すのが、素数判定のアルゴリズムです。
while (start <= end) {
    var check = 2;
    var isPrime = true;
    while (check < start) {
        if (start % check === 0) {
            isPrime = false;
        }
        check++;
    }
    if (isPrime) {
        kotae.push(start);
    }
    start++;
}

10

100

・・・・・・・・・・・・・・

チェック用の数字

始めの数字を取り出す

3

4

9

・・・・・・・・・・・・・・・

10

調べたい数字

最初は2を取り出す※1で割っても素数とは関係ないため1は無視

2

÷

「割り切れるから素数じゃない!」

調べたい数字を1つ増やして、このくり返しは終わる。

チェック用の数字は「今チェックされてる数字」より、

1小さい数が最大。

11

12

※10~100の範囲を調べる場合

素数計算アルゴリズムのイメージ

  • 今のアルゴリズムを絵にしてみるとこんなイメージです。
    • ここでは、開始値【10】から終わり値【100】までの素数を調べるとします。
  • 1つ目の数字をチェックする動きです。開始値【10】のことです。10は当然、割り切れますね。

2

100

・・・・・・・・・・・・・・

次の数字を取り出す

3

4

10

・・・・・・・・・・・・・・・

11

先ほどと同じく最初は2を取り出す

2

÷

12

素数計算アルゴリズムのイメージ

  • 1つめの数字(10)が割り切れたため、10をチェックするのは終わりました。(falseになりました)
  • 次は1つ増やして11を調べます。当然11は、2で割り切れません。

チェック用の数字

11

調べたい数字

2

「割り切れないから、次の数字でチェックが必要!」【チェック用の数字】を1つ増やして次のチェックへ。

  • 割り切れなかったので、チェック用の数字】を1つ増やします。
  • 【調べたい数字】は11のままです。

100

・・・・・・・・・・・・・・・

チェック用の数字

調べたい数字はそのまま

4

10

・・・・・・・・・・・・・・・

11

次の数字を取りだす

3

÷

11

12

素数計算アルゴリズムのイメージ

  • チェック用の数字を3にして、11から割ります。

調べたい数字

3

  • 3でも割り切れませんので、次は4に、次は5に、とチェック用の数字を変えていきます。これを調べたい数字より-1の数字までくり返します。(今回は11なので、【11割る10】までくり返します)
  • 11は最後まで割り切れません。つまりは素数であることがわかります。
    • 割り切れなかった(false)にならなかったので、配列kotaeに11が追加されます。

「割り切れないから、次の数字でチェックが必要!」【チェック用の数字を1つ増やし】て次のチェックへ。

10

100

・・・・・・・・・・・・

4

10

・・・・・・・・・・

11

3

÷

11

12

外側のwhile

内側のwhile

素数計算アルゴリズムのイメージ

  • これが先ほどのコードでの動きです。

JSファイル

}
  document.getElementById("answer").innerHTML = kotae;
}

素数をサイトに表示させる

  • さて、先ほどの処理がすべて終わると(調べたい数字のすべてのチェックが終わると)、配列kotaeの中に、わりきれなかった数、つまりは素数だけが代入されているはずです。
  • 後は、下記のコードで、HTMLのDOMを操作し、サイトにすべての素数を表示しています。
  • ブラウザで計算させてみましょう。

最終調整

  • このままでも、素数を調べる処理自体は問題ないのですが、実は一つ大きな問題があります。
  • それは計算範囲(はんい)の限界値(げんかいち)が設定されていない事です。
  • コンピューターといえ、無限に計算が出来るわけではありません。
  • 特にJSはブラウザで処理していますので、計算が多くなりすぎると処理が追いつかず、ブラウザが固まってしまいます。
  • どれくらいイケるか?はパソコンや、他の処理の影響(えいきょう)でかわってくるのでなんとも言えませんが、おそらく50000ぐらいから固まります。
  • 試しに100000(10万)以上の数を計算させて試してみましょう。
    • ※固まるまで数字をあげてみて、限界ラインを探してみましょう。固まったらブラウザを読み込みなおしてください。(F5キーを押すとブラウザの更新ができます)

function prime() {
    var start = parseInt(document.formPrime.start.value,10);
    var end = parseInt(document.formPrime.end.value,10);
→   if (end - start > 80000) {
→        window.alert('調べる範囲は80000以下にしてください。');
→   }else{
         var kotae = [];
         while (start <= end) {
             var check = 2;
             var isPrime = true;
〜以下略〜

JSファイル

最終調整

  • このままでは利用者が、予期せぬエラーで悩む事になりますので、改良しましょう。

  • JSファイルの、矢印のコードを追加しましょう。

  • 何をしているかは、もう見ればわかるかと思いますが、「入力された数値の範囲が、80000以下の場合だけ処理を実行する」というif文を追加していますね。

  • その場合実行される【window.alert()】(ウインドウ.アラート)は、画面上にエラーウィンドウを表示する関数です。実際に試してみてください。

function prime() {
    var start = parseInt(document.formPrime.start.value,10);
    var end = parseInt(document.formPrime.end.value,10);
    if (end - start > 80000) {
        window.alert('調べる範囲は80000以下にしてください。');
    }else{
        var kotae = [];
        while (start <= end) {
            var check = 2;
            var isPrime = true;
→           while (check <= Math.sqrt(start)) {
                if (start % check === 0) {
                    isPrime = false;
                }
                check++;
            }
〜以下略〜

JSファイル

アルゴリズムの改良

  • さて、ここからはさらに良いプログラムにするために、一工夫です。

  • 現在の素数計算のアルゴリズム(方法)は「割り切れるかどうか、すべての数字を調べる」というアルゴリズムなので、間違いではないものの、無駄な処理が多いです。

  • 出来る限り処理を軽くするために右の矢印の部分を変更してみましょう。※詳しくは次。

function prime() {
    var start = parseInt(document.formPrime.start.value,10);
    var end = parseInt(document.formPrime.end.value,10);
    if (end - start > 500000) {
        window.alert('調べる範囲は500000以下にしてください。');
    }else{
        var kotae = [];
        while (start <= end) {
            var check = 2;
            var isPrime = true;
→           while (check <= Math.sqrt(start)) {
                if (start % check === 0) {
                    isPrime = false;
                }
                check++;
            }
〜以下略〜

JSファイル

アルゴリズムの改良

  • Math.sqrt()というのは、平方根(へいほうこん)にする関数で、()中に入れた数字(今回はstart)の平方根が求められます。※「平方根なんて習ってないぞ!」て人は、今は気にしないでください。
  • この状態で、先ほどまでのコードでは計算出来なかった数で計算してみてください。(30万ぐらいはいけると思う)
    • ※先ほど追加した、80000以下の時だけ、という指定も増やしておきましょう。(500000以下など)

function prime() {
    var start = parseInt(document.formPrime.start.value,10);
    var end = parseInt(document.formPrime.end.value,10);
    if (end - start > 500000) {
        window.alert('調べる範囲は500000以下にしてください。');
    }else{
        var kotae = [];
        while (start <= end) {
            var check = 2;
            var isPrime = true;
→           while (check <= Math.sqrt(start)) {
                if (start % check === 0) {
                    isPrime = false;
                }
                check++;
            }
〜以下略〜

JSファイル

アルゴリズムの改良

  • このようにアルゴリズムを変える事で、より無駄のないプログラムになります。

    こういったアルゴリズムの基本は数学です。今回のプログラムも、過去に数学者が見つけ出した法則をプログラムにしただけです。(実際はもっと良いアルゴリズムはあると思います)

console.log( kotae.length );
//配列kotaeの要素の数が表示される

JSファイル

.length(レングス)を使ってみよう

  • ほかにもより良いサイトにするためのアイデアは色々考えられます。

  • 例えば、今の状態だと、素数がいくつあったのか?自分で数える必要があります。2,3個ならともかく100個とかだと数えてられないですよね?

  • そのため、自動で素数の個数が表示されるようにしてみましょう。

  • これは.配列の組み込みメソッドである【.length】(レングス)を使えば簡単にできます。

  • .lengthとは、「長さ」という意味で、これは使えば【配列の要素(ようそ)数】を出してくれます。

  • 後は、HTMLで表示スペースを作ってあげて、表示させるだけです。

〜〜
    }
     document.getElementById("answer").innerHTML = kotae;
→ document.getElementById("kazu").innerHTML = kotae.length+'個の素数が見つかりました。';
  }
〜〜

HTMLファイル

JSファイル

〜〜
     <input type="button" name="btn" value="計算" onclick="prime()" class="formControl">
     <textarea rows="10" id="answer" class="formControl" readonly></textarea>
→    <div id="kazu"></div>
     </form>
〜〜
  • 下の矢印のコードを追加して、サイトを確認してみましょう。
    • HTMLファイルにも忘れずに追加しましょう。

.length(レングス)を使ってみよう

var arr = [1,2,3];
var goukei = 0;
for(var i=0; i<arr.length; i++){
    goukei = goukei+arr[i];
}
console.log(goukei);
  • .lengthは非常によく使うメソッドで、代表的な使われ方なのは下のような使われ方です。

    • この例では、要素を全部足した合計数が表示されます。(下の例では6が表示される)

.length(レングス)を使ってみよう

  • このようにfor文の繰り返しの条件に.lengthを指定することで、【配列の要素の数だけ、なにか処理をさせる】ということが出来るので、配列が使いやすくなります。

  • 完成させた「素数計算サイト」ですが、実はバグが残っています。
  • それは開始値に1が入力されてしまうと、1も素数としてと判定されてしまうことです。
    • ※数学では「1は素数には含めない」と定義されています。
  • 1を素数として計算させないためにはどうすれば良いか、考えて見てください。※色々な方法があります。

最終問題

  • さらに、その考えた方法で、1が素数として処理されないようにプログラムを変更してください。
    • 完成したら見せてください。
  • おつかれさまです!
  • これで素数計算サイトはひとまず完成ですが、もっと自分だけのオリジナル感を出すため、今まで学んだこと(画像を貼ったり、色を変えるなど)して見た目を変更するのも良いでしょう。
  • すべて終えたら、サーバにアップロードし、インターネット上に公開しましょう。
    • アップロードの手順は、「アップロード方法」のスライドで確認してください。

+オリジナル要素