用python脚本实现Php素数分解
有一个执行素因子分解的用python脚本实现Php素数分解,php,python,algorithm,prime-factoring,Php,Python,Algorithm,Prime Factoring,有一个执行素因子分解的python脚本。它速度很快,在不到一秒钟的时间内就能跑完。但是有一些用于php的函数运行速度非常慢。它取一个参数(长整数),比如1278426847636566097,然后计算素数分解。返回具有2个索引的数组。这个数字的结果是: Array ( [0] => 1233387599 [1] => 1036516703 ) python脚本:(getpq.py) prime.py: # NOTICE!!! This is copied from https://
python
脚本。它速度很快,在不到一秒钟的时间内就能跑完。但是有一些用于php
的函数运行速度非常慢。它取一个参数(长整数),比如1278426847636566097,然后计算素数分解。返回具有2个索引的数组。这个数字的结果是:
Array ( [0] => 1233387599 [1] => 1036516703 )
python脚本:(getpq.py)
prime.py:
# NOTICE!!! This is copied from https://stackoverflow.com/questions/4643647/fast-prime-factorization-module
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 or n % 2 == 0:
return False
elif n < 1:
raise ValueError("Out of bounds, first argument must be > 0")
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(10000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
def primefactors(n, sort=False):
factors = []
limit = int(n ** .5) + 1
for checker in smallprimes:
if checker > limit: break
while n % checker == 0:
factors.append(checker)
n //= checker
limit = int(n ** .5) + 1
if checker > limit: 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 * b) // gcd(a, b)
#注意!!!这是从https://stackoverflow.com/questions/4643647/fast-prime-factorization-module
随机输入
def底漆如下(N):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
#“”“输入N>=6,返回素数列表,2 0”)
elif n<\u小素数集:
返回smallprimeset中的n
d=n-1
s=0
当d%2==0时:
d/=2
s+=1
对于范围内的重复(精度):
a=随机随机。随机范围(2,n-2)
x=功率(a、d、n)
如果x==1或x==n-1:继续
对于范围(s-1)内的r:
x=功率(x,2,n)
如果x==1:返回False
如果x==n-1:中断
否则:返回False
返回真值
# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
布雷特(北):
如果n%2==0:返回2
如果n%3==0:返回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
当g==1时:
x=y
对于范围(r)内的i:
y=(功率(y,2,n)+c)%n
k=0
当k1:
打破
返回g
smallprimes=primesbelow(10000)#可能看起来很低,但1000*1000=1000000,因此这将充分考虑每个小于1000000的组合
def primefactors(n,sort=False):
因子=[]
极限=整数(n**.5)+1
对于smallprimes中的检查器:
如果检查器>限制:中断
当n%checker==0时:
因素。附加(检查)
n/=检查程序
极限=整数(n**.5)+1
如果检查器>限制:中断
如果n<2:返回系数
当n>1时:
如果是iPrime(n):
因子。追加(n)
打破
factor=pollard_brent(n)#试训部门没有完全考虑到这一因素,转而使用pollard brent
factors.extend(primefactors(factor))#递归到pollard brent返回的不一定是primefactor的factor
n/=系数
if sort:factors.sort()
回报率
def因子分解(n):
因子={}
对于primefactors(n)中的p1:
尝试:
系数[p1]+=1
除KeyError外:
系数[p1]=1
回报率
totients={}
def totient(n):
如果n==0:返回1
try:返回到客户端[n]
除KeyError外:通过
tot=1
对于p,exp在因式分解(n)中。items():
总数*=(p-1)*p**(实验-1)
总和[n]=总和
返回总数
def gcd(a、b):
如果a==b:返回a
当b>0:a,b=b,a%b
归还
def lcm(a、b):
返回abs(a*b)//gcd(a,b)
因为我不懂python,有什么方法可以在php中实现这一点吗
注意:我发现一个非常糟糕的算法,用php实现,大约需要600秒:
public function primefactor($num) {
$sqrt = sqrt($num);
for ($i = 2; $i <= $sqrt; $i++) {
if ($num % $i == 0) {
return array_merge($this->primefactor($num/$i), array($i));
}
}
return array($num);
}
公共函数primefactor($num){
$sqrt=sqrt($num);
对于($i=2;$i primefactor($num/$i),数组($i));
}
}
返回数组($num);
}
源代码有。你需要研究“素因子分解”算法。如果您将PHP作为一项需求添加到搜索中,您可以找到比上述暴力方法更好的实现代码。开始
请注意,Python方法没有显示关于算法的任何内容:包prime具有内置算法,而您给出的代码仅调用了该算法。我读过Python包使用概率方法(通过类似300位数字的测试,这些方法100%准确)。当你做研究的时候,要注意这些。将有多种通用语言的实现;我知道至少Python、java和C++。< /P>这是Python代码,但是在C中优化的方法快得多,但是我不确定有更好的方法来找到素因子,这是一个通用的解决方案。有许多复杂程度不同的算法已在大多数常见编程语言中实现。您给出的php是一个幼稚的尝试划分,这是最糟糕的算法之一。请看维基百科上关于保理的页面。这个问题对于堆栈溢出来说太宽泛了(或者离题了,可以理解为需要一个类似于Python
prime
模块的php库)。我编辑了我的帖子。但是关于你提到的链接,我以前找到过,但是maxn
是2^31-1=2147483647,这是数据类型的限制。对于您的应用程序,您需要转换为长整数类型。
public function primefactor($num) {
$sqrt = sqrt($num);
for ($i = 2; $i <= $sqrt; $i++) {
if ($num % $i == 0) {
return array_merge($this->primefactor($num/$i), array($i));
}
}
return array($num);
}