我要尋找一個實現或獲得的ñ的因式分解在任一蟒蛇,僞代碼或其他任何東西也可讀清晰算法。有幾個要求/事實:快速因式分解模塊
- ñ是1和2之間〜20個位數
- 沒有預先計算的查找表,記憶化是好的,但。
- 不需要是數學上證明(如果需要時,如能依靠哥德巴赫猜想)
- 不需要精確,允許是概率性/確定性,如果需要
我需要一個快速因式分解算法,不僅適用於其自身,還適用於許多其他算法,如計算歐拉phi(n)。
我已經嘗試過維基百科等其他算法,但是我無法理解它們(ECM),或者我無法從算法(Pollard-Brent)創建工作實現。
我對Pollard-Brent算法很感興趣,所以對它的任何更多信息/實現都會非常好。
謝謝!
編輯
附近有一座小搞亂後,我已經創建了一個非常快的黃金/分解模塊。它結合了一個優化的試用分割算法,Pollard-Brent算法,miller-rabin素數測試和我在互聯網上找到的速度最快的primesieve。 gcd是一個普通的Euclid的GCD實現(二進制Euclid的GCD是,比常規的要慢很多,比較慢)。
賞金
哦,快樂,可以獲得賞金!但我怎樣才能贏得它?
- 在我的模塊中查找優化或錯誤。
- 提供替代/更好的算法/實現。
最完整/有建設性的答案獲得賞金。
最後模塊本身:
import random
def primesbelow(N):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
#""" Input N>=6, Returns a list of primes, 2 <= p < N """
correction = N % 6 > 1
N = {0:N, 1:N-1, 2:N+4, 3:N+3, 4:N+2, 5:N+1}[N%6]
sieve = [True] * (N // 3)
sieve[0] = False
for i in range(int(N ** .5) // 3 + 1):
if sieve[i]:
k = (3 * i + 1) | 1
sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]
smallprimeset = set(primesbelow(100000))
_smallprimeset = 100000
def isprime(n, precision=7):
# http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
if n < 1:
raise ValueError("Out of bounds, first argument must be > 0")
elif n <= 3:
return n >= 2
elif n % 2 == 0:
return False
elif n < _smallprimeset:
return n in smallprimeset
d = n - 1
s = 0
while d % 2 == 0:
d //= 2
s += 1
for repeat in range(precision):
a = random.randrange(2, n - 2)
x = pow(a, d, n)
if x == 1 or x == n - 1: continue
for r in range(s - 1):
x = pow(x, 2, n)
if x == 1: return False
if x == n - 1: break
else: return False
return True
# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
def pollard_brent(n):
if n % 2 == 0: return 2
if n % 3 == 0: return 3
y, c, m = random.randint(1, n-1), random.randint(1, n-1), random.randint(1, n-1)
g, r, q = 1, 1, 1
while g == 1:
x = y
for i in range(r):
y = (pow(y, 2, n) + c) % n
k = 0
while k < r and g==1:
ys = y
for i in range(min(m, r-k)):
y = (pow(y, 2, n) + c) % n
q = q * abs(x-y) % n
g = gcd(q, n)
k += m
r *= 2
if g == n:
while True:
ys = (pow(ys, 2, n) + c) % n
g = gcd(abs(x - ys), n)
if g > 1:
break
return g
smallprimes = primesbelow(1000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
def primefactors(n, sort=False):
factors = []
for checker in smallprimes:
while n % checker == 0:
factors.append(checker)
n //= checker
if checker > n: break
if n < 2: return factors
while n > 1:
if isprime(n):
factors.append(n)
break
factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
n //= factor
if sort: factors.sort()
return factors
def factorization(n):
factors = {}
for p1 in primefactors(n):
try:
factors[p1] += 1
except KeyError:
factors[p1] = 1
return factors
totients = {}
def totient(n):
if n == 0: return 1
try: return totients[n]
except KeyError: pass
tot = 1
for p, exp in factorization(n).items():
tot *= (p - 1) * p ** (exp - 1)
totients[n] = tot
return tot
def gcd(a, b):
if a == b: return a
while b > 0: a, b = b, a % b
return a
def lcm(a, b):
return abs((a // gcd(a, b)) * b)
@wheaties - 那會是什麼',而檢查*檢查<= num`是有。 – Amber 2011-01-10 04:30:11
你可能會發現這個線程很有用:http://stackoverflow.com/questions/1024640/calculating-phik-for-1kn/1134851#1134851 – RBarryYoung 2011-01-18 05:51:20
爲什麼在標準庫中沒有這樣的東西?當我搜索時,我發現的只有一百萬個歐拉項目解決方案提案,而其他人則指出它們存在缺陷。這不是圖書館和錯誤報告的目的嗎? – endolith 2013-09-30 23:15:23