【備忘録】素数判定・素数リスト

python3
あくまで備忘録なんで雑に記録します

試し割り法(高速化の為、2以上の、奇数だけ、√nまで)

①0・1は外す
②2は入れる
③先に偶数NG判定
④3以降√nまでの奇数で、割って判定

def is_prime(n):
    if n == 0 or n == 1:#0・1は非素数
        return False
    elif n == 2:#2は素数
        return True
    elif n % 2 == 0:#先に2で割って偶数はアウト
        return False
    for i in range(3, int(n**0.5) + 1, 2):#3以上の奇数、√nまでで割る
        if n % i == 0:
            return False
    return True

is_prime(9999973)#0.0002秒

エラトステネスのふるい(リスト)

①0・1は外す
②2〜√nまで、Falseなら飛ばす(事前にさらに小さい素数の倍数はFalseにされているから)
③↑の理由で、初見は素数になるはずだから、スタートを『i × 2』にしておく
④最終的にTrueを出力

def primes_list(n):
    is_prime = [True] * (n + 1)#まずはnまでの数字、is_primeリスト全部Trueにする
    is_prime[0] = False#0は非素数
    is_prime[1] = False#1は非素数
    for i in range(2, int(n**0.5) + 1):#2〜√nまでのiで回す
        if not is_prime[i]:#Falseなら飛ばす(事前にさらに小さい素数の倍数はFalseにされているから)
            continue
        for j in range(i * 2, n + 1, i):#2〜初見はTrue(素数)だけど、その倍数は全てFalse
            is_prime[j] = False#例:2なら[4,6,8...]、3なら[6,9,12...]、5なら[10.15...]をFalse
    return [i for i in range(n + 1) if is_prime[i]]#is_primeリスト上のTrueにはそのままiを入れる

primes_list1(10**7)#約3秒

若干改良したバージョン(偶数を省いて、奇数の奇数倍だけ調査)たいしてかわらない

def primes_list2(n):
    is_prime = [True] * (n + 1)#まずはnまでの数字、is_primeリスト全部Trueにする
    is_prime[0] = False#0は非素数
    is_prime[1] = False#1は非素数
    for k in range(4, n+1, 2):#先に偶数だけ反転
        is_prime[k] = False
    for i in range(3, int(n**0.5) + 1, 2):#3〜√nの奇数(ステップ2)で回す
        if not is_prime[i]:#Falseなら飛ばす(事前にさらに小さい素数の倍数はFalseにされているから)
            continue
        for j in range(i, n + 1, i * 2):#奇数の奇数倍は全てFalse
            is_prime[j] = False#例:2なら[4,6,8...]、3なら[6,9,12...]、5なら[5,10,15...]をFalse
            is_prime[i] = True#だけど初見だから、Trueに戻す
    return [i for i in range(n + 1) if is_prime[i]]#is_primeリスト上のTrueにはそのままiを入れる

primes_list2(10**7)#約2.4秒

エラトステネスのふるい(判定・おそい)

リストを作って判定は遅い

def is_prime(n):
    primes_list = [True] * (n + 1)#まずはnまでの数字、primes_listリスト全部Trueにする
    primes_list[0] = False#0は非素数
    if n != 0:
        primes_list[1] = False#1は非素数
    for i in range(2, int(n**0.5) + 1):#2〜√nまでのiで回す
        if not primes_list[i]:#Falseなら飛ばす(事前にさらに小さい素数の倍数はFalseにされているから)
            continue
        for j in range(i * 2, n + 1, i):#2〜初見はTrue(素数)だけど、その倍数は全てFalse
            primes_list[j] = False#例:2なら[4,6,8...]、3なら[6,9,12...]、5なら[10.15...]をFalse
    return primes_list[n]#primes_list上の数値をそのまま返す

is_prime(9999973)#2.4秒

コメント

タイトルとURLをコピーしました