在Python中考虑一个数字

时间:2013-04-15 03:22:35

标签: python loops primes prime-factoring sieve-of-eratosthenes

这是我的代码:

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

我知道我的方法甚至不是很接近,但你能帮助我做到这一点吗?

4 个答案:

答案 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*ba < 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筛子中的TrueFalse那样。然后使用这个最小因子筛来对每个给定的数字进行有效因子分解,在相同的范围内,通过它们的因子连续除以最小值,这可以通过筛子中的直接查找而不是测试来有效地找到。重新:

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 [])

video with details - Factorizing number in Python