[英]Python Finding Prime Factors
兩部分問題:
這是我在網上找到的素數分解代碼 [注意:此代碼不正確。 請參閱下面 Stefan 的回答以獲得更好的代碼。] :
n = 600851475143
i = 2
while i * i < n:
while n % i == 0:
n = n / i
i = i + 1
print(n)
#takes about ~0.01secs
i = 1
while i < 100:
i += 1
#takes about ~3secs
這個問題是我在 google 上搜索"python prime factorization"
時出現的第一個鏈接。 正如@quangpn88 所指出的,這個算法對於完美的平方是錯誤的(!) ,例如n = 4, 9, 16, ...
但是,@quangpn88 的修復也不起作用,因為如果最大的素數,它會產生不正確的結果factor 出現 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
行。 所以你說你了解基礎知識,但你不確定它是如何工作的。 首先,這是對它源自的 Project Euler 問題的一個很好的回答。 我對這個問題做了很多研究,這是迄今為止最簡單的回應。
出於解釋的目的,我讓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)
這個解釋使用了兩個while
循環。 關於while
循環的最重要的事情是它們會一直運行,直到它們不再為true
為止。
外循環指出,雖然i * i
不大於n
(因為最大的質因子永遠不會大於n
平方根),但在內循環運行后將i
加1
。
內部循環指出,當i
平均分為n
,將n
替換為n
除以i
。 這個循環持續運行,直到它不再為真。 對於n=20
和i=2
, n
替換為10
,然后再次替換為5
。 因為2
不能均勻地分成5
,循環在n=5
停止,外循環結束,產生i+1=3
。
最后,因為3
squared 大於5
,所以外循環不再為true
並打印出n
的結果。
感謝您發布此信息。 在意識到它究竟是如何工作之前,我一直看着代碼。 希望這就是您在回復中尋找的內容。 如果沒有,請告訴我,我可以進一步解釋。
看起來人們正在做 Project Euler 的事情,你自己編寫解決方案。 對於其他想要完成工作的人,有一個primefac 模塊可以非常快速地處理非常大的數字:
#!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 素數檢驗來檢查數字是否為素數。 您可以在此處找到它的 Python 實現。
始終使用timeit
模塊為您的代碼計時,第二個只需要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]
"""
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]
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
樣本輸出:
蟒蛇測試.py 68
[2, 2, 17]
如果您正在尋找維護良好的預先編寫的代碼,請使用來自SymPy的函數sympy.ntheory.primefactors 。
它返回n
的素因數的排序列表。
>>> from sympy.ntheory import primefactors
>>> primefactors(6008)
[2, 751]
將列表傳遞給max()
以獲得最大的質因數: max(primefactors(6008))
如果您想要n
的質因數以及它們中的每一個的多重性,請使用sympy.ntheory.factorint 。
給定一個正整數
n
,factorint(n)
返回一個字典,其中包含n
的質因子作為鍵,它們各自的重數作為值。
>>> from sympy.ntheory import factorint
>>> factorint(6008) # 6008 = (2**3) * (751**1)
{2: 3, 751: 1}
該代碼針對 Python 3.6.9 和 SymPy 1.1.1 進行了測試。
代碼錯誤為 100。它應該檢查 case 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)
我的代碼:
# 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)]
看看這個,它可能對你的理解有所幫助。
#program to find the prime factors of a given number
import sympy as smp
try:
number = int(input('Enter a number : '))
except(ValueError) :
print('Please enter an integer !')
num = number
prime_factors = []
if smp.isprime(number) :
prime_factors.append(number)
else :
for i in range(2, int(number/2) + 1) :
"""while figuring out prime factors of a given number, n
keep in mind that a number can itself be prime or if not,
then all its prime factors will be less than or equal to its int(n/2 + 1)"""
if smp.isprime(i) and number % i == 0 :
while(number % i == 0) :
prime_factors.append(i)
number = number / i
print('prime factors of ' + str(num) + ' - ')
for i in prime_factors :
print(i, end = ' ')
這是我的 python 代碼:它可以快速檢查素數,並從最高到最低檢查素數。 如果沒有新的數字出來,你就必須停下來。 (對此有什么想法嗎?)
import math
def is_prime_v3(n):
""" Return 'true' if n is a prime number, 'False' otherwise """
if n == 1:
return False
if n > 2 and n % 2 == 0:
return False
max_divisor = math.floor(math.sqrt(n))
for d in range(3, 1 + max_divisor, 2):
if n % d == 0:
return False
return True
number = <Number>
for i in range(1,math.floor(number/2)):
if is_prime_v3(i):
if number % i == 0:
print("Found: {} with factor {}".format(number / i, i))
最初問題的答案會在幾分之一秒內到達。
以下是兩種有效生成給定數的質因數的方法:
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')
由於沒有人試圖用舊的 nice reduce
方法來破解它,所以我要從事這個職業。 此方法對於此類問題並不靈活,因為它對參數數組執行重復操作的循環,並且默認情況下無法中斷此循環。 在我們為這樣的中斷循環實現我們自己的interupted reduce
之后,門打開了:
from functools import reduce
def inner_func(func, cond, x, y):
res = func(x, y)
if not cond(res):
raise StopIteration(x, y)
return res
def ireducewhile(func, cond, iterable):
# generates intermediary results of args while reducing
iterable = iter(iterable)
x = next(iterable)
yield x
for y in iterable:
try:
x = inner_func(func, cond, x, y)
except StopIteration:
break
yield x
之后我們就可以使用一些與標准 Python reduce 方法的輸入相同的func
。 讓這個func
以下列方式定義:
def division(c):
num, start = c
for i in range(start, int(num**0.5)+1):
if num % i == 0:
return (num//i, i)
return None
假設我們要對一個數 600851475143 進行因式分解,重復使用該函數后該函數的預期輸出應該是這樣的:
(600851475143, 2) -> (8462696833 -> 71), (10086647 -> 839), (6857, 1471) -> None
元組的第一項是division
方法所取的數字,並嘗試除以最小的除數,從第二項開始,以該數字的平方根結束。 如果不存在除數,則返回 None。 現在我們需要從這樣定義的迭代器開始:
def gener(prime):
# returns and infinite generator (600851475143, 2), 0, 0, 0...
yield (prime, 2)
while True:
yield 0
最后,循環的結果是:
result = list(ireducewhile(lambda x,y: div(x), lambda x: x is not None, iterable=gen(600851475143)))
#result: [(600851475143, 2), (8462696833, 71), (10086647, 839), (6857, 1471)]
輸出質數除數可以通過以下方式捕獲:
if len(result) == 1: output = result[0][0]
else: output = list(map(lambda x: x[1], result[1:]))+[result[-1][0]]
#output: [2, 71, 839, 1471]
為了提高效率,您可能希望使用位於特定范圍內的預生成素數,而不是該范圍內的所有值。
你不應該循環到數字的平方根! 有時可能是對的,但並非總是如此!
10 的最大質因數是 5,比 sqrt(10) (3.16, aprox) 大。
33 的最大質因數是 11,比 sqrt(33) (5.5,74, aprox) 大。
您將此與適當性混淆了,即如果一個數字的質因數大於其 sqrt,則它必須至少有另一個小於其 sqrt 的質因數。 所以,如果你想測試一個數字是否是素數,你只需要測試直到它的 sqrt。
def prime(n):
for i in range(2,n):
if n%i==0:
return False
return True
def primefactors():
m=int(input('enter the number:'))
for i in range(2,m):
if (prime(i)):
if m%i==0:
print(i)
return print('end of it')
primefactors()
處理 2 后跳過偶數的另一種方法:
def prime_factors(n):
factors = []
d = 2
step = 1
while d*d <= n:
while n>1:
while n%d == 0:
factors.append(d)
n = n/d
d += step
step = 2
return factors
n=int(input("Enter the number"))
if n==1 : #because the below logic doesn't work on 1
print(n)
for i in range(2 , n+1):
if n%i==0 :
n1=i #get factor
for b in range(2,n+1): #check if it is prime
if ((n1%b)==0) & (n1==b):
print(n1)
elif (n1%b)==0 or n1<b: #if not then pass
break
我確信這是最糟糕的邏輯,但這是我在 .py 中擁有的所有知識,該程序將從用戶那里獲得一個數字並打印所有的因數,這些數字是 12 的素數,它將給出 2,3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.