web-dev-qa-db-ja.com

Python素因数を見つける

2部構成の質問:

1)600851475143の最大の素因数を決定しようとすると、このプログラムがオンラインで動作しているように見えました。問題は、プログラムが何をしているのかの基本を理解しているのに、正確にどのように機能するかを理解するのに苦労していることです。また、おそらくすべての数をテストせずに、素因数を見つけることを知っているかもしれない任意の方法と、その方法がどのように機能するかについて、いくつかの光を当てることができればと思います。

素因数分解のためにオンラインで見つけたコードは次のとおりです。

n = 600851475143
i = 2
while i * i < n:
     while n % i == 0:
         n = n / i
     i = i + 1

print (n)

#takes about ~0.01secs

2)なぜそのコードはこのコードよりもはるかに速いのですか?これは単に速度をテストするためであり、それ以外の本当の目的はありませんか?

i = 1
while i < 100:
    i += 1
#takes about ~3secs
41
francium

この質問は、"python prime factorization"をGoogleで検索したときに最初に表示されたリンクです。 @ quangpn88によって指摘されているように、このアルゴリズムはn = 4, 9, 16, ...などの完全な正方形に対してwrong(!)です。ただし、@ quangpn88の修正は機能しません。どちらも、最大の素因数が3回以上発生した場合、n = 2*2*2 = 8n = 2*3*3*3 = 54などの誤った結果が生じるためです。

Pythonの正しいブルートフォースアルゴリズムは次のとおりです。

def largest_prime_factor(n):
    i = 2
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
    return n

これをパフォーマンスコードで使用しないでください。ただし、適度に大きい数でのクイックテストには問題ありません。

In [1]: %timeit largest_prime_factor(600851475143)
1000 loops, best of 3: 388 µs per loop

完全な素因数分解が求められる場合、これはブルートフォースアルゴリズムです。

def prime_factors(n):
    i = 2
    factors = []
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.append(i)
    if n > 1:
        factors.append(n)
    return factors
52
Stefan

OK。あなたは基本を理解していると言いましたが、それがどのように機能するのか正確にはわかりません。まず第一に、これはプロジェクトオイラーの質問に対する素晴らしい答えです。私はこの問題について多くの研究を行ってきましたが、これは群を抜いて最も単純な対応です。

説明のために、n = 20を許可します。実際のProject Euler問題を実行するには、n = 600851475143を使用します。

n = 20 
i = 2

while i * i < n:
    while n%i == 0:
        n = n / i
    i = i + 1

print (n)

この説明では、2つのwhileループを使用します。 whileループについて覚えておくべき最大のことは、trueでなくなるまで実行することです。

外側のループは、i * inより大きくない間(最大の素因数はnの平方根より大きくなることはないため)に、1を追加することを示しますi内側のループが実行された後。

内側のループでは、inに均等に分割されますが、nniで割った値に置き換えられます。このループは、真実でなくなるまで継続的に実行されます。 n=20およびi=2の場合、n10に置き換えられ、再び5に置き換えられます。 25に均等に分割されないため、ループはn=5で停止し、外側のループが終了してi+1=3が生成されます。

最後に、3の2乗が5より大きいため、外側のループはtrueではなくなり、nの結果を出力します。

これを投稿してくれてありがとう。どのように正確に機能するかを理解する前に、私はコードを永遠に見ました。うまくいけば、これはあなたが応答で探しているものです。そうでない場合はお知らせください。さらに説明できます。

30
Will Luce

ユーザーが自分でソリューションをコーディングするプロジェクトオイラーのことをやっているようです。仕事を終わらせたい他の皆のために、 primefac module があります。これは非常に大きな数を非常に素早く行います:

#!python

import primefac
import sys

n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
23
brian d foy

素数の生成には、常に Sieve of Eratosthenes を使用します。

def primes(n):
    if n<=2:
        return []
    sieve=[True]*(n+1)
    for x in range(3,int(n**0.5)+1,2):
        for y in range(3,(n//x)+1,2):
            sieve[(x*y)]=False

    return [2]+[i for i in range(3,n,2) if sieve[i]]

In [42]: %timeit primes(10**5)
10 loops, best of 3: 60.4 ms per loop

In [43]: %timeit primes(10**6)
1 loops, best of 3: 1.01 s per loop

Miller-Rabin primality test を使用して、数値が素数かどうかを確認できます。 Python実装 ここ を見つけることができます。

常に timeit モジュールを使用してコードの時間を計ります。2番目のモジュールは15usのみを取ります。

def func():
    n = 600851475143
    i = 2
    while i * i < n:
         while n % i == 0:
            n = n / i
         i = i + 1

In [19]: %timeit func()
1000 loops, best of 3: 1.35 ms per loop

def func():
    i=1
    while i<100:i+=1
   ....:     

In [21]: %timeit func()
10000 loops, best of 3: 15.3 us per loop
10

27の最大の素因数は3ではありませんか??上記のコードは最速かもしれませんが、27で失敗しますか? 27 = 3 * 3 * 3上記のコードは1を返します。私の知る限り..... 1は素数でも合成でもありません

これがより良いコードだと思う

def prime_factors(n):
    factors=[]
    d=2
    while(d*d<=n):
        while(n>1):            
            while n%d==0:
                factors.append(d)
                n=n/d
            d+=1
    return factors[-1]
7
m0rpheu5

コードは100で間違っています。ケースi * i = nをチェックする必要があります。

私はそれがあるべきだと思う:

while i * i <= n:
    if i * i = n:
        n = i
        break

    while n%i == 0:
        n = n / i
    i = i + 1

print (n)
3
quangpn88
def find_prime_facs(n):
  list_of_factors=[]
  i=2
  while n>1:
    if n%i==0:
      list_of_factors.append(i)
      n=n/i
      i=i-1
    i+=1  
  return list_of_factors
3
Perviz Mamedov

これを行う別の方法:

import sys
n = int(sys.argv[1])
result = []
for i in xrange(2,n):
    while n % i == 0:
        #print i,"|",n
        n = n/i
        result.append(i)

    if n == 1: 
        break

if n > 1: result.append(n)
print result

サンプル出力:
python test.py 68
[2、2、17]

3
Rajesh
"""
The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

"""

from sympy import primefactors
print primefactors(600851475143)[-1]
3

私のコード:

# METHOD: PRIME FACTORS
def prime_factors(n):
    '''PRIME FACTORS: generates a list of prime factors for the number given
    RETURNS: number(being factored), list(prime factors), count(how many loops to find factors, for optimization)
    '''
    num = n                         #number at the end
    count = 0                       #optimization (to count iterations)
    index = 0                       #index (to test)
    t = [2, 3, 5, 7]                #list (to test)
    f = []                          #prime factors list
    while t[index] ** 2 <= n:
        count += 1                  #increment (how many loops to find factors)
        if len(t) == (index + 1):
            t.append(t[-2] + 6)     #extend test list (as much as needed) [2, 3, 5, 7, 11, 13...]
        if n % t[index]:            #if 0 does else (otherwise increments, or try next t[index])
            index += 1              #increment index
        else:
            n = n // t[index]       #drop max number we are testing... (this should drastically shorten the loops)
            f.append(t[index])      #append factor to list
    if n > 1:
        f.append(n)                 #add last factor...
    return num, f, f'count optimization: {count}'

投票数が最も多いコードと比較すると、非常に高速でした

    def prime_factors2(n):
        i = 2
        factors = []
        count = 0                           #added to test optimization
        while i * i <= n:
            count += 1                      #added to test optimization
            if n % i:
                i += 1
            else:
                n //= i
                factors.append(i)
        if n > 1:
            factors.append(n)
        return factors, f'count: {count}'   #print with (count added)

テスト、(注意、最適化をテストするために各ループにCOUNTを追加しました)

# >>> prime_factors2(600851475143)
# ([71, 839, 1471, 6857], 'count: 1472')
# >>> prime_factors(600851475143)
# (600851475143, [71, 839, 1471, 6857], 'count optimization: 494')

私は、このコードを簡単に変更して(最大の要因)またはその他の必要なものを取得できると考えています。私はどんな質問にも心を開いています。私の目標は、より大きな素数や因子についてもこれをさらに改善することです。

2
Dean Jones

Numpyを使用する場合は、n以下のすべての素数の配列を作成する方法があります。

[ i for i in np.arange(2,n+1) if 0 not in np.array([i] * (i-2) ) % np.arange(2,i)]

1
xenakas

以下は、指定された数の素因数を効率的に生成する2つの方法です。

from math import sqrt


def prime_factors(num):
    '''
    This function collectes all prime factors of given number and prints them.
    '''
    prime_factors_list = []
    while num % 2 == 0:
        prime_factors_list.append(2)
        num /= 2
    for i in range(3, int(sqrt(num))+1, 2):
        if num % i == 0:
            prime_factors_list.append(i)
            num /= i
    if num > 2:
        prime_factors_list.append(int(num))
    print(sorted(prime_factors_list))


val = int(input('Enter number:'))
prime_factors(val)


def prime_factors_generator(num):
    '''
    This function creates a generator for prime factors of given number and generates the factors until user asks for them.
    It handles StopIteration if generator exhausted.
    '''
    while num % 2 == 0:
        yield 2
        num /= 2
    for i in range(3, int(sqrt(num))+1, 2):
        if num % i == 0:
            yield i
            num /= i
    if num > 2:
        yield int(num)


val = int(input('Enter number:'))
prime_gen = prime_factors_generator(val)
while True:
    try:
        print(next(prime_gen))
    except StopIteration:
        print('Generator exhausted...')
        break
    else:
        flag = input('Do you want next prime factor ? "y" or "n":')
        if flag == 'y':
            continue
        Elif flag == 'n':
            break
        else:
            print('Please try again and enter a correct choice i.e. either y or n')
0
G.G.