web-dev-qa-db-ja.com

Python言語のisPrime関数

それで、インターネットから少し助けを借りてこの問題を解決することができました。これが私が得たものです。

def isPrime(n):
    for i in range(2,int(n**0.5)+1):
        if n%i==0:
            return False

    return True

しかし、私の質問は本当にそれを行う方法ですが、なぜですか。 1は「素数」と見なされないことを理解し、範囲内でANYTHINGで除算すると自動的に素数になるため、Falseステートメントを返すことを理解しています。しかし、私の質問は「n」の二乗はここでどのような役割を果たします?ご清聴ありがとうございました

追伸私は非常に経験が浅く、1か月前にプログラミングを紹介したばかりです。

インターネット上に浮かぶ多くの素数テストのうち、次の素数テストを検討してください。

def is_prime(n):
  if n == 2 or n == 3: return True
  if n < 2 or n%2 == 0: return False
  if n < 9: return True
  if n%3 == 0: return False
  r = int(n**0.5)
  f = 5
  while f <= r:
    print '\t',f
    if n%f == 0: return False
    if n%(f+2) == 0: return False
    f +=6
  return True    

素数5003を考えます。

print is_prime(5003)

プリント:

 5
 11
 17
 23
 29
 35
 41
 47
 53
 59
 65
True

r = int(n**0.5)は70と評価されます(5003の平方根は70.7318881411であり、int()はこの値を切り捨てます)

最初のいくつかのテスト、およびループの途中でのテストのため、ループは6番めごとに評価する必要があります。

5002の次の奇数(2以外のすべての偶数は素数ではないため)について考えてみましょう。同じものが出力されます:

 5
False

x*y == y*xなので、制限は平方根です。5005が5で割り切れるので、素数ではないことを見つけるために、関数は1ループするだけです。 5 X 1001 == 1001 X 5(および両方とも5005)なので、5で知っていることを知るためにループ内で1001に到達する必要はありません!


次に、使用しているアルゴリズムを見てみましょう。

def isPrime(n):
    for i in range(2,int(n**0.5)+1):
        if n%i==0:
            return False

    return True

2つの問題があります。

  1. nが2未満であり、2未満の素数がないかどうかはテストしません。
  2. すべての偶数とすべての奇数を含む2〜n ** 0.5のすべての数をテストします。 2で割り切れる2より大きい数値はすべて素数ではないため、2より大きい奇数をテストするだけで少し高速化できます。

そう:

def isPrime2(n):
    if n==2 or n==3: return True
    if n%2==0 or n<2: return False
    for i in range(3,int(n**0.5)+1,2):   # only odd numbers
        if n%i==0:
            return False    

    return True

OK-それは約30%スピードアップします(私はそれをベンチマークしました...)

is_primeを使用したアルゴリズムは、6番目の整数ごとにループをループしているため、まだ約2倍高速です。 (もう一度、ベンチマークを行いました。)


サイドノート:x ** 0.5は平方根です:

>>> import math
>>> math.sqrt(100)==100**0.5
True

サイドノート2: primality testing はコンピューターサイエンスの興味深い問題です。

74
dawg

n**.5を使用すると、nの2乗ではなく、平方根を取得します。

数20を検討してください。整数係数は1、2、4、5、10、および20です。20を2で割って10を取得すると、チェックせずに10で割り切れることがわかります。 4で割って5を取得すると、5をチェックせずに4と5の両方で割り切れることがわかります。

ファクターのこの中間点に到達すると、それ以前にファクターとしてまだ認識されていないものを確認するための数字がなくなります。したがって、何かが素数であるかどうかを確認するために途中まで行く必要があり、この中間点は数値の平方根を取ることで見つけることができます。

また、1が素数ではない理由は、素数が1とそれ自体の2つの因子を持つと定義されているためです。つまり、2は1 * 2、3は1 * 3、5は1 * 5です。ただし、1(1 * 1)には1つの因子しかありません。したがって、この定義を満たしていません。

19
cpuguy89

質問は少し前に尋ねられましたが、私はあなたのために短い解決策を持っています

isPrime(Number):
    return 2 in [Number,2**Number%Number]

数値が2の代わりに素数の場合、数学演算は常に2を返します。ただし、2が指定された数値の場合、探しているリストに追加されます。

2^5=32    32%5=2
2^7=128   128%7=2
2^11=2048 2048%11=2

等々 ...

isPrime()は、NumberがPrimeの場合はTrueを返し、そうでない場合はFalseを返します。

12
Daniel

以下では浮動小数点演算は行われません。これは高速で、より高い引数を許容します。平方根だけに行かなければならない理由は、数値がその平方根よりも大きい因子を持っている場合、それもそれよりも小さい因子を持っているからです。

def is_prime(n):
    """"pre-condition: n is a nonnegative integer
    post-condition: return True if n is prime and False otherwise."""
    if n < 2: 
         return False;
    if n % 2 == 0:             
         return n == 2  # return False
    k = 3
    while k*k <= n:
         if n % k == 0:
             return False
         k += 2
    return True
10
ncmathsadist

数の平方根を見つけることは効率のためです。例えば。 36の係数を見つけようとしている場合、36を形成するためにそれ自体で乗算できる最大数は6です。7* 7 = 49。

したがって、36のすべての係数に6以下の数を掛ける必要があります。

4
dibble

このメソッドは、ここでの再帰的および列挙的なメソッドよりも遅くなりますが、 ウィルソンの定理 を使用し、1行だけです:

from math import factorial

def is_prime(x):
    return factorial(x - 1)  % x == x - 1
4
aikramer2
def is_prime(x):
    if x < 2:
        return False
    Elif x == 2:
        return True  
    for n in range(2, x):
        if x % n ==0:
            return False
    return True
4
likarson

遅れているかどうかはわかりませんが、今後誰かを助けるためにここに置いておきます。

(n)の平方根、つまりint(n ** 0.5)を使用して、プログラムで計算を強制される数値の範囲を減らします。

たとえば、100の素数性をテストするためにトライアル除算を行うことができます。100のすべての約数を見てみましょう。

2、4、5、10、20、25、50ここで、最大係数は100/2 = 50であることがわかります。これは、すべてのnに当てはまります。すべての約数はn/2以下です。除数を詳しく見ると、それらの一部が冗長であることがわかります。リストを異なる方法で記述した場合:

100 = 2×50 = 4×25 = 5×20 = 10×10 = 20×5 = 25×4 = 50×2冗長性が明らかになります。 √100である10に達すると、除数は単に反転して繰り返します。したがって、√nより大きいテスト除数をさらに排除できます。

16のような別の数を取ります。

その除数は2,4,8です

16 = 2 * 8、4 * 4、8 * 2。

16の平方根である4に達した後、すでに2 * 8として行った8 * 2を繰り返したことに注意してください。このパターンはすべての数値に当てはまります。

繰り返しを避けるため、nの平方根までの素数性をテストします。

したがって、浮動小数点数の範囲が必要ないため、平方根をintに変換します。

詳細については、ウィキペディアの素数性テストを参照してください。

2
Stephen-Njoroge

これは私の方法です:

import math

def isPrime(n):
    'Returns True if n is prime, False if n is not prime. Will not work if n is 0 or 1'

    # Make sure n is a positive integer
    n = abs(int(n))

    # Case 1: the number is 2 (prime)
    if n == 2: return True

    # Case 2: the number is even (not prime)
    if n % 2 == 0: return False

    # Case 3: the number is odd (could be prime or not)

    # Check odd numbers less than the square root for possible factors 
    r = math.sqrt(n)
    x = 3 
    while x <= r:
        if n % x == 0: return False  # A factor was found, so number is not prime
        x += 2 # Increment to the next odd number

    # No factors found, so number is prime  
    return True 

元の質問に答えるために、-n ** 0.5nの平方根と同じです。複合数はalwaysの平方根以下の係数を持つため、この数の後に係数のチェックを停止できます。これは、nごとに2からnまでのすべての因子をチェックするよりも高速です。これは、nが大きくなるにつれて時間を節約できるため、チェックする数字が少ないためです。

2
def isPrime(num,div=2):
    if(num==div):
        return True
    Elif(num % div == 0):
        return False
    else:
        return isPrime(num,div+1)

=============================================
編集済み

def is_prime(num, div = 2):
    if num == div: return True
    Elif num % div == 0: return False
    Elif num == 1: return False
    else: return is_prime(num, div + 1)
2
namco

あなたが書くコードはすべて効率的でなければなりません。あなたのような初心者にとって最も簡単な方法は、数の除数をチェックすることです'n' from 2 to(n-1)。非常に大きな数を考慮すると、これには多くの時間がかかります。平方根法は、比較の回数を減らしてコードを高速化するのに役立ちます。アルゴリズムの設計と分析の複雑さについて読む。

2
Vipin Rai

Pythonに擬似コード( https://en.wikipedia.org/wiki/Primality_test )を実装しました。このヘルプを願っています。

# original pseudocode https://en.wikipedia.org/wiki/Primality_test
def isPrime(n):
    # Corner Cases
    if (n<= 1): return False
    Elif (n<= 3): return True
    Elif (n%2 == 0 or n%3 == 0): return False

    i = 5
    while i*i<=n:
        if (n%i==0 or n%(i+2)==0): return False
        i += 6

    return True;

%timeit isPrime(800)
1
madeinQuant
isPrime=lambda x: all(x % i != 0 for i in range(int(x**0.5)+1)[2:])

そして、ここでそれを使用する方法を行きます

isPrime(2) == False
isPrime(5) == True
isPrime(7) == True

すべての素数を見つけるには、次を使用します。

filter(isPrime, range(4000)[2:])[:5]
=> [2, 3, 5, 7, 11]

この場合の5は、検出される素数の数と、素数が検索される4000の最大範囲を示すことに注意してください。

1
test30
def is_prime(x):  
    if x < 2:  
        return False  
    for n in range(2, (x) - 1):  
        if x % n == 0:  
            return False  
    return True
1

これは私のnp方法です:

def is_prime(x):
    if x < 4:
        return True
    if all([(x > 2), (x % 2 == 0)]):
        return False
    else:
        return np.array([*map(lambda y: ((x % y) == 0).sum(), np.arange(1, x + 1))]).sum() == 2

パフォーマンスは次のとおりです。

%timeit is_prime(2)
%timeit is_prime(int(1e3))
%timeit is_prime(5003)

10000 loops, best of 3: 31.1 µs per loop
10000 loops, best of 3: 33 µs per loop
10 loops, best of 3: 74.2 ms per loop
0
O.rka
def is_prime(n):
if (n==2 or n==3): return True
if(n<=1 or n%2==0 or n%3==0 ): return False
for i in range(6,int((n**0.5)) + 2,6):
    if(n%(i-1)==0 or n%(i+1)==0):
        return False
return True
0
Peyman Naseri

int(n**0.5)は、sqrt(n)の下限値で、nの累乗2 (n**2)と混同しました。 nnot素数の場合、1 < i <= j < nのような2つの数字i * j = nが必要です。

ここで、sqrt(n) * sqrt(n) = nは、i,jのいずれかがsqrt(n)よりも大きい(または等しい)と仮定しているため、もう一方はsqrt(n)よりも小さい(または等しい)必要があることを意味します。

そうであるため、[2, sqrt(n)]の範囲の整数を反復処理するのに十分です。そして、それはまさに投稿されたコードがやっていることです。

あなたが本物のsmartassとして出てきたい場合は、次のワンライナー関数を使用してください:

import re
def is_prime(n):    
    return not re.match(r'^1?$|^(11+?)\1+$',n*'1')

「魔法の正規表現」の説明を見つけることができます here

0
alfasin

それはコードアカデミーでの練習であり、それが私がそれを下に渡す方法です...

def is_prime(x):  

    # If number(x) is evenly divided by following dividers then number(x) is not prime

    divider = [2, 3, 5, 7]

    # An empty list to be able to check whether number(x) is evenly divided:

    remainder = []

    # exceptions for numbers 1,2,3,5,7:
    if x < 2:
        return False
    if x in divider:
        return True
    else:
        for nums in divider:
            remainder.append(x % nums)
        if 0 in remainder:
            return False
        else:
            return True
0
Murat Karınca
def fun(N):#prime test
if N>1 :
    for _ in xrange(5):
        Num=randint(1,N-1)
        if pow(Num,N-1,N)!=1:
            return False
    return True
return False

数値が素数であれば真、そうでなければ偽

0
chinmay rakshit
def is_prime(n):
    n=abs(n)
    if n<2:    #Numbers less than 2 are not prime numbers
        return "False"
    Elif n==2: #2 is a prime number
        return "True"
    else:
        for i in range(2,n): # Highlights range numbers that can't be  a factor of prime number n. 
            if n%i==0:
                return "False" #if any of these numbers are factors of n, n is not a prime number
    return "True" # This is to affirm that n is indeed a prime number after passing all three tests
0
Ayo