这是我的代码:
def factorize(n):
sieve = [True] * (n + 1)
for x in range(2, int(len(sieve) ** 0.5) + 1):
if sieve[x]:
for i in range(x + x, len(sieve), x):
sieve[i] = False
lowerPrimes = i for i in range(2, len(sieve)) if sieve[i]] and (n % i == 0)]
return lowerPrimes
factorize(n)
返回给定值n
的所有素数因子。正如您所看到的,它首先为n
制作了一个Eratosthenes筛子,然后使用列表推导来返回筛子中所有n
因子的值。它为此目的工作得相对较好,但是,我希望它返回一个列表,这样如果你将其中的每个项目相乘,结果就是n
。你明白了吗?
例如,factorize(99020)
会返回[2, 5, 4951]
,但我希望它返回[2, 2, 5, 4951]
,2*2*5*4951 = 99020
。
我知道我的方法甚至不是很接近,但你能帮助我做到这一点吗?
答案 0 :(得分:7)
Eratosthenes筛选可帮助您找到低于特定限制的素数。找到特定数字的因素并不能帮助你。
如果你想这样做,我能看到的最简单的方法就是这样:
def factors(n):
while n > 1:
for i in range(2, n + 1):
if n % i == 0:
n /= i
yield i
break
for factor in factors(360):
print factor
这基本上找到n
的最小因子(保证为素数),将n
除以该数字并重复该过程,直到n
等于1
}。
输出结果为:
2
2
2
3
3
5
他们乘以原来的数字:
>>> from operator import mul
>>> reduce(mul, factors(360))
360
答案 1 :(得分:6)
the answer by Blender中的代码非常好,但该算法缺乏一个非常重要的方面:它测试方式太多了。例如。试图将n=392798360393
因子化,这是一个素数,它会尝试将它除以它下面的所有数字(包括它自己)。这将需要很多时间。
真的有必要吗?如果n == a*b
和a < b
找到a
,我们确实不需要按n
测试除b
。我们知道它也将n
分开,因为n/a == b
暗示n/b == a
。因此,我们只需要测试潜在因子a
小于(或等于)潜在因子b
。也就是说,直到达到该数字的平方根。
此外,对于每个缩小的n
,不要从2开始,而是start from the previous value of i
可以:
def factors(n): # (cf. https://stackoverflow.com/a/15703327/849891)
j = 2
while n > 1:
for i in xrange(j, int(sqrt(n+0.05)) + 1):
if n % i == 0:
n /= i ; j = i
yield i
break
else:
if n > 1:
yield n; break
实际上,通过此代码对9000009
进行因式分析在Ideone上需要0.08秒,而不是0.59秒。
这保证只生成素数(因为我们将找到的每个因子分开,并且我们以非递减顺序尝试候选者)。如果我们一次考虑多个数字,那么首先生成素数然后仅通过素数进行测试(通过所有数字进行a.o.t.测试,如上所述)的开销将是值得的。因为只考虑一个数字,它可能是不值得的,这取决于你的黄金代的速度。
但是,当一次分解多个数字时,真正应该做的是首先创建 最小因子筛,我们在给定范围内标记每个数字它最小(素数)因子(由筛子产生)而不是像Eratosthenes筛子中的True
或False
那样。然后使用这个最小因子筛来对每个给定的数字进行有效因子分解,在相同的范围内,通过它们的因子连续除以最小值,这可以通过筛子中的直接查找而不是测试来有效地找到。重新:
def sfs_factorize(nums):
top = max(nums)
sv = smallest_factor_sieve(top)
for k in nums:
fs = [] ; n = k
while n > 1:
f = sv[n] # no testing
n /= f
fs.append(f)
print( k, list(fs))
答案 2 :(得分:0)
我不熟悉这个问题是否应该删除或者其他什么,但无论如何我都会帮忙。
我认为你的筛子部分是正确的。
关键是使用while
循环继续多次分割有效的素因子。
factors = []
sieve[0] = sieve[1] = False # So I don't have to worry about trying to skip over these two
for testFactIndex, isPrime in enumerate(sieve):
if isPrime:
while n%testFactIndex == 0:
n = n/testFactIndex
factors.append(testFactIndex)
return factors
答案 3 :(得分:0)
我的python 3.8脚本(使用赋值表达式)
f = lambda n: (p:=[next(i for i in range(2, n+1) if n % i == 0)] if n>1 else [])+(f(n//p[0]) if p else [])