web-dev-qa-db-ja.com

PythonのシンプルなPrime Generator

誰かが私がこのコードで間違っていることを教えてもらえますか?とにかく「カウント」を印刷しています。非常に単純な素数ジェネレーター(空想なものはありません)が必要です。

import math

def main():
    count = 3
    one = 1
    while one == 1:
        for x in range(2, int(math.sqrt(count) + 1)):
            if count % x == 0: 
                continue
            if count % x != 0:
                print count

        count += 1
33
marc lincoln

いくつかの問題があります:

  • Xで除算しなかったのに、なぜカウントを出力するのですか?それは素数を意味するのではなく、この特定のxがそれを分割しないことだけを意味します
  • continueは次のループ反復に移動しますが、breakを使用して実際に停止したい場合

いくつかの修正を加えたコードを次に示します。素数のみが出力されます。

import math

def main():
    count = 3
    
    while True:
        isprime = True
        
        for x in range(2, int(math.sqrt(count) + 1)):
            if count % x == 0: 
                isprime = False
                break
        
        if isprime:
            print count
        
        count += 1

より効率的な素数生成については、他の人が示唆しているように、エラストテネスのふるいを参照してください。以下に、多くのコメントを含む最適化された素敵な実装を示します。

# Sieve of Eratosthenes
# Code by David Eppstein, UC Irvine, 28 Feb 2002
# http://code.activestate.com/recipes/117119/

def gen_primes():
    """ Generate an infinite sequence of prime numbers.
    """
    # Maps composites to primes witnessing their compositeness.
    # This is memory efficient, as the sieve is not "run forward"
    # indefinitely, but only as long as required by the current
    # number being tested.
    #
    D = {}
    
    # The running integer that's checked for primeness
    q = 2
    
    while True:
        if q not in D:
            # q is a new prime.
            # Yield it and mark its first multiple that isn't
            # already marked in previous iterations
            # 
            yield q
            D[q * q] = [q]
        else:
            # q is composite. D[q] is the list of primes that
            # divide it. Since we've reached q, we no longer
            # need it in the map, but we'll mark the next 
            # multiples of its witnesses to prepare for larger
            # numbers
            # 
            for p in D[q]:
                D.setdefault(p + q, []).append(p)
            del D[q]
        
        q += 1

ジェネレータを返すことに注意してください。

146
Eli Bendersky
def is_prime(num):
    """Returns True if the number is prime
    else False."""
    if num == 0 or num == 1:
        return False
    for x in range(2, num):
        if num % x == 0:
            return False
    else:
        return True

>> filter(is_prime, range(1, 20))
  [2, 3, 5, 7, 11, 13, 17, 19]

リストに最大20個の素数をすべて取得します。私はエラトステネスのふるいを使用することもできましたが、あなたは非常にシンプルなものが欲しいと言っていました。 ;)

14
aatifh
print [x for x in range(2,100) if not [t for t in range(2,x) if not x%t]]
8
SergioAraujo

reは強力です:

import re


def isprime(n):
    return re.compile(r'^1?$|^(11+)\1+$').match('1' * n) is None

print [x for x in range(100) if isprime(x)]

###########Output#############
[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]
8
FelixHo
def primes(n): # simple Sieve of Eratosthenes 
   odds = range(3, n+1, 2)
   sieve = set(sum([range(q*q, n+1, q+q) for q in odds],[]))
   return [2] + [p for p in odds if p not in sieve]

>>> primes(50)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

数値が素数かどうかをテストするには:

>>> 541 in primes(541)
True
>>> 543 in primes(543)
False
4
dansalmo

以下はsimple(Python 2.6.2)ソリューション... OPの元のリクエスト(現在6か月前)に沿ったものです。 「プログラミング101」コースで完全に受け入れられるソリューションである必要があります...したがって、この投稿。

import math

def isPrime(n):
    for i in range(2, int(math.sqrt(n)+1)):
        if n % i == 0: 
            return False;
    return n>1;

print 2
for n in range(3, 50):
    if isPrime(n):
        print n

この単純な「ブルートフォース」方式は、最新のPCでは約16,000までの数値に対して「十分に高速」です(私の2GHzボックスでは約8秒かかりました)。

明らかに、これはすべての偶数の素数、またはすべての単一の数の3、5、7などの倍数を再計算しないことにより、はるかに効率的に実行できます。 Sieveを参照してくださいエラトステネス (上記のelibenの実装を参照)または Sieve of Atkin .

警告Emptor:私はpython noobです。私が福音として言っていることは何もしないでください。

3
corlettk

私の意見では、常に機能的なアプローチを取ることが最善です。

そこで、最初に関数を作成して、数値が素数かどうかを確認し、必要に応じてループまたは他の場所で使用します。

def isprime(n):
      for x in range(2,n):
        if n%x == 0:
            return False
    return True

次に、単純なリスト内包表記またはジェネレータ式を実行して、素数のリストを取得します。

[x for x in range(1,100) if isprime(x)]
2
mmrs151

奇数のみを考慮した単純な最適化を使用した別の単純な例。遅延ストリーム(Pythonジェネレーター)で行われたすべて。

使用法:primes = list(create_prime_iterator(1、30))

import math
import itertools

def create_prime_iterator(rfrom, rto):
    """Create iterator of prime numbers in range [rfrom, rto]"""
    prefix = [2] if rfrom < 3 and rto > 1 else [] # include 2 if it is in range separately as it is a "weird" case of even prime
    odd_rfrom = 3 if rfrom < 3 else make_odd(rfrom) # make rfrom an odd number so that  we can skip all even nubers when searching for primes, also skip 1 as a non prime odd number.
    odd_numbers = (num for num in xrange(odd_rfrom, rto + 1, 2))
    prime_generator = (num for num in odd_numbers if not has_odd_divisor(num))
    return itertools.chain(prefix, prime_generator)

def has_odd_divisor(num):
    """Test whether number is evenly divisable by odd divisor."""
    maxDivisor = int(math.sqrt(num))
    for divisor in xrange(3, maxDivisor + 1, 2):
        if num % divisor == 0:
            return True
    return False

def make_odd(number):
    """Make number odd by adding one to it if it was even, otherwise return it unchanged"""
    return number | 1
1
Sharas

素数を直接計算したい場合はどうですか:

def oprime(n):
counter = 0
b = 1
if n == 1:
    print 2
while counter < n-1:
    b = b + 2
    for a in range(2,b):
        if b % a == 0:
            break
    else:
        counter = counter + 1
        if counter == n-1:
            print b
1

これは宿題のように見えるので、詳細な説明ではなくヒントを示します。間違っていると思ったら訂正してください。

除数が均等になったときに救済する限り、元気です。

しかし、oneに分割されない数字さえ表示されたらすぐに 'count'を出力しています。たとえば、2は均等に9に分割されませんが、9が素数になるわけではありません。 no範囲内の番号が一致することを確認するまで続けてください。

(他の人が答えたように、Sieveははるかに効率的な方法です...この特定のコードがあなたの望むことをしていない理由を理解するのを助けるだけです)

1
Paul Roub

ここに、大丈夫な複雑さ(長さnの配列をソートするよりも低い)とベクトル化の両方を備えたEratosthenesのnumpyバージョンがあります。

import numpy as np 
def generate_primes(n):
    is_prime = np.ones(n+1,dtype=bool)
    is_prime[0:2] = False
    for i in range(int(n**0.5)+1):
        if is_prime[i]:
            is_prime[i*2::i]=False
    return np.where(is_prime)[0]

タイミング:

import time    
for i in range(2,10):
    timer =time.time()
    generate_primes(10**i)
    print('n = 10^',i,' time =', round(time.time()-timer,6))

>> n = 10^ 2  time = 5.6e-05
>> n = 10^ 3  time = 6.4e-05
>> n = 10^ 4  time = 0.000114
>> n = 10^ 5  time = 0.000593
>> n = 10^ 6  time = 0.00467
>> n = 10^ 7  time = 0.177758
>> n = 10^ 8  time = 1.701312
>> n = 10^ 9  time = 19.322478

SymPy は、Pythonシンボリック数学用のライブラリです。素数を生成するための関数をいくつか提供します。

isprime(n)              # Test if n is a prime number (True) or not (False).

primerange(a, b)        # Generate a list of all prime numbers in the range [a, b).
randprime(a, b)         # Return a random prime number in the range [a, b).
primepi(n)              # Return the number of prime numbers less than or equal to n.

prime(nth)              # Return the nth prime, with the primes indexed as prime(1) = 2. The nth prime is approximately n*log(n) and can never be larger than 2**n.
prevprime(n, ith=1)     # Return the largest prime smaller than n
nextprime(n)            # Return the ith prime greater than n

sieve.primerange(a, b)  # Generate all prime numbers in the range [a, b), implemented as a dynamically growing sieve of Eratosthenes. 

下記は用例です。

>>> import sympy
>>> 
>>> sympy.isprime(5)
True
>>> list(sympy.primerange(0, 100))
[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]
>>> sympy.randprime(0, 100)
83
>>> sympy.randprime(0, 100)
41
>>> sympy.prime(3)
5
>>> sympy.prevprime(50)
47
>>> sympy.nextprime(50)
53
>>> list(sympy.sieve.primerange(0, 100))
[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]
0
SparkAndShine

範囲内のすべての素数を検索する場合は、これを実行できます。

def is_prime(num):
"""Returns True if the number is prime
else False."""
if num == 0 or num == 1:
    return False
for x in range(2, num):
    if num % x == 0:
        return False
else:
    return True
num = 0
itr = 0
tot = ''
while itr <= 100:
    itr = itr + 1
    num = num + 1
    if is_prime(num) == True:
        print(num)
        tot = tot + ' ' + str(num)
print(tot)

while its <=と範囲の番号を追加するだけです。
出力:
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 101

0
user9311010

ここに私が持っているものがあります:

def is_prime(num):
    if num < 2:         return False
    Elif num < 4:       return True
    Elif not num % 2:   return False
    Elif num < 9:       return True
    Elif not num % 3:   return False
    else:
        for n in range(5, int(math.sqrt(num) + 1), 6):
            if not num % n:
                return False
            Elif not num % (n + 2):
                return False

    return True

数の約数について既に素数に対してのみチェックするため、大きな数に対してはかなり高速です。

素数のリストを生成したい場合、次のことができます:

# primes up to 'max'
def primes_max(max):
    yield 2
    for n in range(3, max, 2):
        if is_prime(n):
            yield n

# the first 'count' primes
def primes_count(count):
    counter = 0
    num = 3

    yield 2

    while counter < count:
        if is_prime(num):
            yield num
            counter += 1
        num += 2

効率を上げるために、ここでジェネレータを使用することが望ましい場合があります。

そして、単に言及する代わりに、

one = 1
while one == 1:
    # do stuff

あなたは単に言うことができます:

while 1:
    #do stuff
0
fengshaun

ジェネレーターの使用:

def primes(num):
    if 2 <= num:
        yield 2
    for i in range(3, num + 1, 2):
        if all(i % x != 0 for x in range(3, int(math.sqrt(i) + 1))):
            yield i

使用法:

for i in primes(10):
    print(i)

2、3、5、7

0
Vlad Bezden

User107745に似ていますが、二重否定の代わりに「all」を使用します(もう少し読みやすいですが、同じパフォーマンスだと思います)。

import math
[x for x in xrange(2,10000) if all(x%t for t in xrange(2,int(math.sqrt(x))+1))]

基本的に、(2、100)の範囲でxを反復処理し、range(2、x)のすべてのtに対してmod == 0を持たないもののみを選択します。

別の方法としては、おそらく素数を入力するだけです。

primes = set()
def isPrime(x):
  if x in primes:
    return x
  for i in primes:
    if not x % i:
      return None
  else:
    primes.add(x)
    return x

filter(isPrime, range(2,10000))
0
vtlinh

リスト内包表記を使用して、かなりエレガントな方法で素数のリストを作成できます。 here: から取得

>>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
>>> primes = [x for x in range(2, 50) if x not in noprimes]
>>> print primes
>>> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
0
randlet
  • Continueステートメントが間違っているように見えます。

  • 2が最初の素数であるため、2から開始します。

  • 「while True:」を記述して、無限ループを取得できます。

0
starblue
def genPrimes():
    primes = []   # primes generated so far
    last = 1      # last number tried
    while True:
        last += 1
        for p in primes:
            if last % p == 0:
                break
        else:
            primes.append(last)
            yield last
0
def check_prime(x):
    if (x < 2): 
       return 0
    Elif (x == 2): 
       return 1
    t = range(x)
    for i in t[2:]:
       if (x % i == 0):
            return 0
    return 1
0
kn3l

可能性のあるすべての除数が、チェックする数値を均等に分割しないようにする必要があります。この場合、可能な除数の1つだけが数値を均等に分割しない場合に、チェックしている数値を印刷します。

また、番号が素数ではないことがすでにわかっている場合、continueは次の可能な除数をチェックするだけなので、continueステートメントを使用したくありません。

0
David Locke