Python寻找主要因素

fra*_*ium 46 python primes

两部分问题......

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
Run Code Online (Sandbox Code Playgroud)

2)为什么代码比这段代码快得多(代码只是测试速度而没有其他真正的用途)

i = 1
while i < 100:
    i += 1
#takes about ~3secs
Run Code Online (Sandbox Code Playgroud)

Ste*_*fan 57

这个问题是我用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
Run Code Online (Sandbox Code Playgroud)

不要在性能代码中使用它,但对于中等大小的数字进行快速测试是可以的:

In [1]: %timeit largest_prime_factor(600851475143)
1000 loops, best of 3: 388 µs per loop
Run Code Online (Sandbox Code Playgroud)

如果寻求完整的素数因子分解,这就是蛮力算法:

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
Run Code Online (Sandbox Code Playgroud)

  • 对于奇数,你可以做`i + = 2`而不是1,并以`i = 3`而不是2开头.不知道会有多少性能差异. (3认同)
  • 感谢分享!为什么`n // = i`?我以为`//`是地板分割,在这种情况下应该等同于`/`。`//`比`/`快吗? (2认同)

Wil*_*uce 31

好.所以你说你了解基础知识,但你不确定它是如何工作的.首先,这是对其源于的项目欧拉问题的一个很好的答案.我已经对这个问题做了很多研究,这是迄今为止最简单的回答.

为了解释,我会让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)
Run Code Online (Sandbox Code Playgroud)

此解释使用两个while循环.关于while循环最重要的事情是它们一直运行直到它们不再存在true.

外环指出,虽然i * i不大于n(因为最大的主要因素决不会比的平方根较大n),添加1i内循环运行后.

内循环表示虽然i均匀分为n,但nn除以代替i.此循环持续运行,直到它不再成立.对于n=20i=2,n被替换为10,然后再被替换5.因为2不均匀分成5,循环停止n=5和外循环结束,产生i+1=3.

最后,因为3平方大于5,外循环不再true打印结果n.

感谢发布此内容.在了解代码的确切工作原理之前,我永远查看了代码.希望这是您在回复中寻找的内容.如果没有,请告诉我,我可以进一步解释.

  • '因为最大的素数因子永远不会大于n'的平方根 - 为什么?10的最大素因子是5,而5大于10的平方根 (10认同)
  • 当'n = 4`时的情况怎么样?这似乎是打印4作为素数 (3认同)
  • @Mathai我猜Will意味着最小的质因数,请参阅:http://math.stackexchange.com/questions/102755/greatest-prime-factor-of-n-is-less-than-square-root-of -n-证明 (3认同)
  • 这样,8的最大素数因子是1! (2认同)
  • @Mathai因为我们将除数除以数字,我们可以在i*i> n时停止.然后最后一个`n`是原始数字的最大因子(如果我们用`if`替换内部`while`:``if n%i == 0:n = n/i else:i = i + 1 `). (2认同)

bri*_*foy 24

看起来人们正在做项目欧拉的事情,你自己编写解决方案.对于其他想要完成工作的人来说,有一个primefac模块非常快速地执行非常大的数字:

#!python

import primefac
import sys

n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
Run Code Online (Sandbox Code Playgroud)

  • 它可用于Python3吗?我找不到那个版本. (5认同)
  • @ArpadHorvath查看https://github.com/elliptic-shiho/primefac-fork (2认同)

Ash*_*ary 12

对于素数代,我总是使用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
Run Code Online (Sandbox Code Playgroud)

您可以使用Miller-Rabin素性测试来检查数字是否为素数.你可以在这里找到它的Python实现.

总是使用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
Run Code Online (Sandbox Code Playgroud)


m0r*_*eu5 9

不是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]
Run Code Online (Sandbox Code Playgroud)

  • @mabraham如上所述,1既不是素数也不是复合数!它对于2,3无效,因为d从2开始!所以我们可以在其中添加一个if条件! (2认同)
  • 我知道所有这些事情。你似乎不知道代码不起作用。;-) (2认同)

小智 8

"""
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]
Run Code Online (Sandbox Code Playgroud)


小智 7

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
Run Code Online (Sandbox Code Playgroud)


qua*_*n88 5

代码错误为 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)
Run Code Online (Sandbox Code Playgroud)


小智 5

这样做的另一种方法:

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
Run Code Online (Sandbox Code Playgroud)

示例输出:
python test.py 68
[2, 2, 17]


小智 5

我的代码:

# 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}'
Run Code Online (Sandbox Code Playgroud)

我将其与得票最多的代码进行了比较,速度非常快

    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)
Run Code Online (Sandbox Code Playgroud)

测试,(注意,我在每个循环中添加了一个 COUNT 来测试优化)

# >>> prime_factors2(600851475143)
# ([71, 839, 1471, 6857], 'count: 1472')
# >>> prime_factors(600851475143)
# (600851475143, [71, 839, 1471, 6857], 'count optimization: 494')
Run Code Online (Sandbox Code Playgroud)

我认为可以轻松修改此代码以获得(最大因子)或任何其他需要的东西。我对任何问题持开放态度,我的目标是针对更大的素数和因子进一步改进这一点。


Sri*_*ila 5

如果您正在寻找维护良好的预先编写的代码,请使用来自SymPy的函数sympy.ntheory.primefactors

它返回 的素因数的排序列表n

>>> from sympy.ntheory import primefactors
>>> primefactors(6008)
[2, 751]
Run Code Online (Sandbox Code Playgroud)

将列表传递给以max()获得最大的素数:max(primefactors(6008))

如果您想要质因数n以及它们中的每一个的多重性,请使用sympy.ntheory.factorint

给定一个正整数nfactorint(n)返回一个字典,其中包含n作为键的质因数和作为值的它们各自的重数。

>>> from sympy.ntheory import factorint
>>> factorint(6008)   # 6008 = (2**3) * (751**1)
{2: 3, 751: 1}
Run Code Online (Sandbox Code Playgroud)

该代码针对 Python 3.6.9 和 SymPy 1.1.1 进行了测试。