【问题标题】:Factorizing a number in Python在 Python 中对数字进行因式分解
【发布时间】:2013-04-07 02:19:08
【问题描述】:

这是我的代码:

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

我知道我的方法还不够接近,但你能帮我做到吗?

【问题讨论】:

  • 由于多个问题,此代码无法运行 - 缩进一个,但更重要的是,您在返回前的最后一行有语法错误。

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


【解决方案1】:

我的 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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 哇,好方法。谢谢。
    【解决方案3】:

    埃拉托色尼筛法可帮助您找到低于特定限制的素数。它并不能真正帮助您找到特定数字的因数。

    如果你想这样做,我能看到的最简单的方法是这样的:

    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
    

    【讨论】:

    • 你的方法非常简单,比我期待的任何东西都要干净得多。对新手程序员有什么建议吗?
    • @user2278662:我不是专家,但我唯一的建议是制作东西。
    • @Jared:我在这里的目标是简单,但你可能是对的。我不确定生成素数的开销是否值得。
    • primes or not primes 与这段代码所做的大量多余测试相比是微不足道的。更多内容在我的回答中。
    • @WillNess:正如我之前所说,我的代码并不意味着高效。我尽可能短地给 OP 一些可以使用的东西。有much better 整数分解算法,如果你想有效地分解整数,为什么不使用其中之一呢?
    【解决方案4】:

    我不太熟悉这个问题是否应该删除或其他什么,但无论如何我都会提供帮助。

    我认为你的筛子部分是正确的。 关键是使用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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 1970-01-01
      相关资源
      最近更新 更多