两部分问题......
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
答案 0 :(得分:49)
这个问题是我用Google搜索"python prime factorization"
时弹出的第一个链接。
正如@ quangpn88指出的那样,这个算法错误(!)用于完美的正方形,例如n = 4, 9, 16, ...
但是,@ 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
答案 1 :(得分:28)
确定。所以你说你了解基础知识,但你不确定它是如何工作的。首先,这是对其源于的项目欧拉问题的一个很好的答案。我已经对这个问题做了很多研究,这是迄今为止最简单的反应。
为了解释,我会让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
的平方根),但添加{{1内循环运行后到1
。
内部循环指出,当i
均分为i
时,将n
替换为n
除以n
。此循环持续运行,直到它不再成立。对于i
和n=20
,i=2
替换为n
,然后再替换为10
。由于5
不会平均分为2
,因此循环会以5
停止,外部循环结束,生成n=5
。
最后,因为i+1=3
平方大于3
,所以外循环不再是5
并打印true
的结果。
感谢您发布此内容。在了解代码的确切工作原理之前,我永远查看了代码。希望这是您在回复中寻找的内容。如果没有,请告诉我,我可以进一步解释。
答案 2 :(得分:21)
看起来人们正在做项目欧拉的事情,你自己编写解决方案。对于其他想要完成工作的人来说,primefac module可以很快地完成非常大的工作:
#!python
import primefac
import sys
n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
答案 3 :(得分:7)
对于素数生成,我总是使用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实现here。
始终使用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
答案 4 :(得分:7)
不是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]
答案 5 :(得分:3)
代码错误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)
答案 6 :(得分:2)
另一种方法:
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]
答案 7 :(得分:2)
"""
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]
答案 8 :(得分:2)
我的代码:
# 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')
我认为可以轻松修改此代码以获取(最大因子)或任何其他需要的代码。我对任何问题都持开放态度,我的目标是针对更大的素数和因数进一步改善这一点。
答案 9 :(得分:2)
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
答案 10 :(得分:1)
如果您要查找维护良好的预写代码,请使用sympy.ntheory.primefactors中的函数SymPy。
它返回n
素数的排序列表。
>>> from sympy.ntheory import primefactors
>>> primefactors(6008)
[2, 751]
将列表传递到max()
以获得最大的素数。
如果您想要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进行了测试。
答案 11 :(得分:1)
检查一下,可能会对您的理解有所帮助。
#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 = ' ')
答案 12 :(得分:0)
如果要使用numpy,这是一种创建所有素数不大于n的数组的方法:
[ i for i in np.arange(2,n+1) if 0 not in np.array([i] * (i-2) ) % np.arange(2,i)]
答案 13 :(得分:0)
以下是有效生成给定数量素数的两种方法:
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')
答案 14 :(得分:0)
由于没有人尝试使用旧的不错的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 method的输入相同的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]
为了提高效率,您可能希望使用位于特定范围内的预生成素数,而不是该范围内的所有值。
答案 15 :(得分:0)
你不应该循环直到数字的平方根!有时可能是对的,但并非总是如此!
10的最大素数因子是5,大于sqrt(10)(3.16,aprox)。
33的最大素数因子是11,大于sqrt(33)(5.5,74,aprox)。
你将这与适当性混淆,后者指出,如果一个数字的素数因子大于其sqrt,则必须至少有另一个其他素数因子小于其sqrt。所以,如果你想测试一个数字是否为素数,你只需要测试直到它的sqrt。
答案 16 :(得分:-1)
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()
答案 17 :(得分:-1)
处理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
答案 18 :(得分:-1)
num_list = []
def primeFactors(n):
for i in range(2,n + 1):
while n % i == 0:
num_list.append(i)
n = n / i
if n == 1:
break
n = 13195
primeFactors(n)
print(num_list)
答案 19 :(得分:-2)
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