pythonで素数判定

#はじめに
##これは初心者による初心者のための記事です。

今回も問題を解いていて、やっと解決できたので、備忘録にするとともに共有しようと思いまして、この記事を書いております。

今回は、ある自然数が素数かどうか判定するプログラムの作成です！


#プログラム作成
さて、さっそく作成していきます。

そもそも、素数とは何なのか、軽く言及しておきます。

・素数：1と、その数自身でしか割り切れることのできない数（１は含まない）


つまり、2~（その数―1）までの数で、その数を割っていき、余りを調べればよさそうだ、と考えました！

そこで、p_judgeという関数を定義していきます
（なんでｐかというと、数学の問題でよく素数はｐであらわされるからです笑）

```Python
#　関数を定義
def p_judge(a):
```
さて、それでは処理の仕方を考えていきます。
まず、2~（その数―1）までの数を代入して、割るという作業がいるので、**for文**が使えそうです！

また、素数か、そうではないか判断するため、処理が分岐しそうです。したがって、**if文**が使えそうです！

以上のことから、forとifを組み合わせれば、うまくいきそうだな、と考えました。

以下が、その処理を表したプログラムです

```PYthon
#　関数を定義
def p_judge(a):
    for x in range(2,a):#2から（調べる数-1）までxに代入
        if a%x == 0:#もしa÷xが割り切れるとき
            print('False')#Falseと出力し
            return#関数の呼び出し元に戻る。
    print('True')#上のプログラムをすべてクリアしたら、Trueと出力
```

これでよさそうですね！！
わかりやすいようにコメントを細かく書いてみました。
もし間違っている場合はご指摘ください。

これで大枠は完成しました！
あとは値をうけとるためにinputを配置、そしてちゃんと定義した関数を使うためにもう少し記述を加えれば完成です。

以下が完成したプログラムです

```Python
a = input()#値を受け取る（この時は文字列として受け取る）
a = int(a)#文字列として受け取ったaを整数に変換

def p_judge(a):
    for x in range(2,a):#2から（調べる数-1）までxに代入
        if a%x == 0:#もしa÷xが割り切れるとき
            print('False')#Falseと出力し
            return#関数の呼び出し元に戻る。

    print('True')#上のプログラムをすべてクリアしたら、Trueと出力

p_judge(a)#それでは、aに対して関数p_judgeを使用
```
はい、完成しました！！


##余談
このプログラムを作るのに、結構時間がかかってしまいました…
というのも、returnとifとforがわかっていなかったんです。

ifとforは関数だと思っていたので、ふつうにその中にreturnを入れて記述していました。
で、いつもエラーで'return outside function'とでて発狂しそうでした笑

これを、新たに関数を定義することで解決したわけですね。
まだまだ初心者なので、わからないことも多いですが、さすがにこの程度で手こずりすぎだろ、と思います。とほほ・・・


##追記
いくつかコメントをいただきましたので、プログラムを修正していきます！

①printではなく、True、Falseを返す関数にするとよい

→printの部分を消して、returnに変えればよさそうです。

②引数として1，0や負の数が与えられた時の処理を考えた方がよい。

→if文を少しいじればうまくいきそうです。

とりあえず、この①、②を反映させるとこのようになります。

```Python
a = input()
a = int(a)

def p_judge(a):
    if a <= 1:#もしaが1以下の数だったら
        return False#Falseを返す
    for x in range(3,a,2):#3からa-1まで、２ずつ増える数をxに代入
        if a%x == 0:
            return False#Falseを返す
        
    return True#Trueを返す

print(p_judge(a))
```
コメントが書かれているところが変わった部分です。

orを使って、一つのif文に入れようとやってみましたが、うまくいかずにやむなく二つに分割しました・・・

続いて修正するのはこの2点です。

③偶数は2以外は素数ではないので、２と偶数の処理だけ最初に済ませ、奇数だけをループすると処理時間を減らせる

④割り切れるかどうかは平方根まで調べればよい。

まず③について修正していきます。
これは、またifをくっつけていけばよさそうです。つまり、2以外の偶数は除けばよいということです。
これを反映させたのが以下のプログラムです

```Python
a = input()
a = int(a)

def p_judge(a):
    if a == 2:#もしaが２なら
        return True#Trueを返す
    elif a <= 1 or a%2 == 0:#もしaが1以下の数またはaが2で割り切れるなら
        return False#Falseを返す
    for x in range(3,a,2):
        if a%x == 0:
            return False
        
    return True

print(p_judge(a))
```

さて、④についてですが、私自身この事実は初めて知りました・・・笑
言われてみれば、確かにそうだなあという感じですね。
合成数の場合は約数が存在しますが、その約数には対になる数があります。（例えば、64なら4×16と16×4など）
そして、その数の折り返し地点がちょうど平方根の部分なわけです。
（64なら8×8で折り返し）だから、平方根まで調べればその先は調べなくてもいいわけですね。
これをプログラムに反映していきます。


平方根はmathモジュール内のsqrtというメソッドであらわせます。
そして、その値の小数点以下を切り捨てるために、同じくmathモジュールのfloorというメソッドを使います。

以下が修正したプログラムです。

```Python
import math#mathモジュールをimport

a = input()
a = int(a)

a = math.sqrt(a)#sqrtを使って、aの平方根を表す
a = math.floor(a)#floorを使って、aの小数点以下を切り捨て

def p_judge(a):
    if a == 2:
        return True
    elif a <= 1 or a%2 == 0:
        return False
    for x in range(3,a+1,2):#aが変わったので、+1する必要がある
        if a%x == 0:
            return False
        
    return True

print(p_judge(a))
```        
これですべて終了です！！
コメントをくださった方々、ありがとうございました！


##おわりに
今回は、素数判定プログラムを作ってみました。
なにかアドバイスなどございましたら気軽にコメントいただけたら、その都度記事に反映させていくつもりです。

最後まで読んでいただきありがとうございました！！！