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
この質問は、"python prime factorization"
をGoogleで検索したときに最初に表示されたリンクです。 @ quangpn88によって指摘されているように、このアルゴリズムはn = 4, 9, 16, ...
などの完全な正方形に対してwrong(!)です。ただし、@ quangpn88の修正は機能しません。どちらも、最大の素因数が3回以上発生した場合、n = 2*2*2 = 8
やn = 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
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 * i
がn
より大きくない間(最大の素因数はn
の平方根より大きくなることはないため)に、1
を追加することを示しますi
内側のループが実行された後。
内側のループでは、i
はn
に均等に分割されますが、n
はn
をi
で割った値に置き換えられます。このループは、真実でなくなるまで継続的に実行されます。 n=20
およびi=2
の場合、n
は10
に置き換えられ、再び5
に置き換えられます。 2
は5
に均等に分割されないため、ループはn=5
で停止し、外側のループが終了してi+1=3
が生成されます。
最後に、3
の2乗が5
より大きいため、外側のループはtrue
ではなくなり、n
の結果を出力します。
これを投稿してくれてありがとう。どのように正確に機能するかを理解する前に、私はコードを永遠に見ました。うまくいけば、これはあなたが応答で探しているものです。そうでない場合はお知らせください。さらに説明できます。
ユーザーが自分でソリューションをコーディングするプロジェクトオイラーのことをやっているようです。仕事を終わらせたい他の皆のために、 primefac module があります。これは非常に大きな数を非常に素早く行います:
#!python
import primefac
import sys
n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
素数の生成には、常に 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
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]
コードは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)
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
これを行う別の方法:
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]
"""
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]
私のコード:
# 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')
私は、このコードを簡単に変更して(最大の要因)またはその他の必要なものを取得できると考えています。私はどんな質問にも心を開いています。私の目標は、より大きな素数や因子についてもこれをさらに改善することです。
Numpyを使用する場合は、n以下のすべての素数の配列を作成する方法があります。
[ i for i in np.arange(2,n+1) if 0 not in np.array([i] * (i-2) ) % np.arange(2,i)]
以下は、指定された数の素因数を効率的に生成する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')