找到数字最大素数因子的有效方法

时间:2014-06-11 15:09:56

标签: python primes prime-factoring factorization

我在我找到的网站上做了这个问题(项目Euler),并且有一个问题涉及找到一个数字的最大素数因子。我的解决方案失败了很多,所以我想知道如何简化这段代码?

""" Find the largest prime of a number """


def get_factors(number):
    factors = []
    for integer in range(1, number + 1):
        if number%integer == 0:
            factors.append(integer)
    return factors

def test_prime(number):
    prime = True
    for i in range(1, number + 1):
        if i!=1 and i!=2 and i!=number:
            if number%i == 0:
                prime = False
    return prime

def test_for_primes(lst):
    primes = []
    for i in lst:
        if test_prime(i):
            primes.append(i)
    return primes


################################################### program starts here
def find_largest_prime_factor(i):
    factors = get_factors(i)
    prime_factors = test_for_primes(factors)
    print prime_factors


print find_largest_prime_factor(22)

#this jams my computer
print find_largest_prime_factor(600851475143)

使用大数字时失败,这是我猜的问题。 (计算机堵塞,告诉我我的内存已用完,并询问我想停止哪些程序)。

************************************ 感谢您的回答。在任何情况下,代码中都存在一些错误。所以这个(低效代码)的固定版本在下面。

""" Find the largest prime of a number """


def get_factors(number):
    factors = []
    for integer in xrange(1, number + 1):
        if number%integer == 0:
            factors.append(integer)
    return factors

def test_prime(number):
    prime = True
    if number == 1 or number == 2:
        return prime
    else:
        for i in xrange(2, number):
            if number%i == 0:
                prime = False
    return prime


def test_for_primes(lst):
    primes = []
    for i in lst:
        if test_prime(i):
            primes.append(i)
    return primes


################################################### program starts here
def find_largest_prime_factor(i):
    factors = get_factors(i)
    print factors
    prime_factors = test_for_primes(factors)
    return prime_factors


print find_largest_prime_factor(x)

12 个答案:

答案 0 :(得分:6)

根据您的方法,您首先在n中生成数字O(n)的所有除数,然后在O(n)的另一test_prime次调用中测试这些除数中的哪一个是素数(无论如何都是指数)。

更好的方法是观察一旦你发现一个数的除数,你可以反复除以它来摆脱所有这些因素。因此,为了获得主要因素,比如830297,你测试所有的小素数(缓存),并且对于每个分数你的数字,你要继续划分:

  • 830297可被13整除,所以现在您将使用830297 / 13 = 63869
  • 进行测试
  • 63869仍可13整除,您在4913
  • 4913不会除以13,下一个素数是17,它将4913除以289
  • 289仍然是17的倍数,你有17这是除数并停止。

为了进一步提高速度,在测试下面的缓存素数100之后,你必须使用test_prime函数测试素数除数(根据@ Ben的答案更新),但继续反向,从sqrt开始。您的号码可以被71整除,下一个号码会sqrt 91992,这有点接近6857,这是最大的素数因素。

答案 1 :(得分:5)

这是我最喜欢的Python简单分解程序:

def factors(n):
    wheel = [1,2,2,4,2,4,2,4,6,2,6]
    w, f, fs = 0, 2, []
    while f*f <= n:
        while n % f == 0:
            fs.append(f)
            n /= f
        f, w = f + wheel[w], w+1
        if w == 11: w = 3
    if n > 1: fs.append(n)
    return fs

基本算法是试验分割,使用素轮产生试验因子。它并不像素数的试验划分那么快,但是不需要计算或存储素数,所以它非常方便。

如果您对使用素数进行编程感兴趣,可以在我的博客上欣赏此essay

答案 2 :(得分:5)

我的解决方案是在C#中。我打赌你可以把它翻译成python。我已经用1到1.000.000.000之间的随机长整数进行测试,并且表现良好。您可以尝试使用在线prime calculator快乐编码来测试结果:)

public static long biggestPrimeFactor(long num) {
    for (int div = 2; div < num; div++) {
        if (num % div == 0) {
            num \= div
            div--;
        }
    }
    return num;
}

答案 3 :(得分:4)

可以通过以下几种方式改进幼稚素性测试:

  1. 分别用2分别测试可分性,然后在3开始循环并按2进行
  2. 以ceil结束你的循环(sqrt(num))。您可以保证找不到高于此数字的主要因素
  3. 事先用筛子生成素数,如果用尽了筛子中的数字,只能转移到天真的方向。
  4. 除了这些简单的修复之外,您还必须查找更有效的分解算法。

答案 4 :(得分:3)

使用Sieve of Eratosthenes来计算素数。

from math import sqrt

def sieveOfEratosthenes(n):
    primes = range(3, n + 1, 2) # primes above 2 must be odd so start at three and increase by 2
    for base in xrange(len(primes)):
        if primes[base] is None:
            continue
        if primes[base] >= sqrt(n): # stop at sqrt of n
            break

        for i in xrange(base + (base + 1) * primes[base], len(primes), primes[base]):
            primes[i] = None
    primes.insert(0,2)
    return filter(None, primes)

答案 5 :(得分:3)

通过试验划分进行素数分解的要点是,仅对一个数字进行因子分解的最有效解决方案不需要任何质数测试。

您只需按升序列举您的可能因素,并将它们从有问题的数字中分开 - 所有这些因素都可以保证是最优的。当当前因子的平方超过被分解的当前数时停止。请参阅user448810's answer中的代码。

通常情况下,试验除法的素数因子化在素数上比在所有数字(或赔率等)上更快,但是当仅对一个数字进行因子分解时,为了先找出要素除以后的次数, 可能的成本高于不断增加的可能因素。此枚举为 O(n),素数生成为 O(n log log n),带the Sieve of Eratosthenes (SoE),其中 n = sqrt(N) 的上限为 N 。通过试验区(TD),复杂度为 O(n 1.5 /(log n) 2

当然,渐近线只是作为指导,实际代码的常数因素可能会改变图像。例如,从herehere派生的Haskell代码的执行时间,分解600851475149(素数):

2..                       0.57 sec
2,3,5,...                 0.28 sec
2,3,5,7,11,13,17,19,...   0.21 sec
primes, segmented TD      0.65 sec    first try
                          0.05 sec    subsequent runs (primes are memoized)
primes, list-based SoE    0.44 sec    first try
                          0.05 sec    subsequent runs (primes are memoized)
primes, array-based SoE   0.15 sec    first try
                          0.06 sec    subsequent runs (primes are memoized)

所以这取决于。当然,将所讨论的复合数量分解为600851475143几乎是瞬时的,因此无关紧要。

答案 6 :(得分:3)

Here is an example in JavaScript

function largestPrimeFactor(val, divisor = 2) { 
    let square = (val) => Math.pow(val, 2);

    while ((val % divisor) != 0 && square(divisor) <= val) {
        divisor++;
    }

    return square(divisor) <= val
        ? largestPrimeFactor(val / divisor, divisor)
        : val;
}

答案 7 :(得分:1)

我将解决方案从@ under5hell转换为Python(2.7x)。多么有效的方式!

java.util.Random

答案 8 :(得分:1)

试试这段代码:

from math import *

def largestprime(n):
    i=2
    while (n>1):
        if (n % i == 0):
            n = n/i
        else:
            i=i+1
    print i     

strinput = raw_input('Enter the number to be factorized : ')
a = int(strinput)
largestprime(a)

答案 9 :(得分:0)

旧的但可能有帮助

def isprime(num):
    if num > 1:
        # check for factors
        for i in range(2,num):
                if (num % i) == 0:
                    return False 
        return True

def largest_prime_factor(bignumber):
    prime = 2
    while bignumber != 1:
        if bignumber % prime == 0:
            bignumber = bignumber / prime
        else:
            prime = prime + 1
            while isprime(prime) == False:
                prime = prime+1
    return prime
number = 600851475143
print largest_prime_factor(number)

答案 10 :(得分:0)

我希望这会有所帮助,也很容易理解。

A = int(input("Enter the number to find the largest prime factor:"))

B = 2

while (B <(A/2)):

    if A%B != 0:
        B = B+1

    else:
        A = A/B
        C = B
        B = 2
print (A)

答案 11 :(得分:0)

这个用于获取最大素数因子的代码,当我运行它时,其值为prime_factor(13195),将在不到一秒的时间内返回结果。 但是当nums值达到6digits时,它将在8秒内返回结果。

任何人都知道解决方案的最佳算法是什么......

def prime_factor(nums):

if nums < 2:
    return 0
primes = [2]
x = 3
while x <= nums:
    for i in primes:
        if x%i==0:
            x += 2
            break
    else:
        primes.append(x)
        x += 2
largest_prime = primes[::-1]
# ^^^ code above to gets all prime numbers

intermediate_tag = []
factor = []
# this code divide nums by the largest prime no. and return if the
# result is an integer then append to primefactor.
for i in largest_prime:
    x = nums/i
    if x.is_integer():
        intermediate_tag.append(x)

# this code gets the prime factors [29.0, 13.0, 7.0, 5.0]     
for i in intermediate_tag:
    y = nums/i
    factor.append(y)



print(intermediate_tag)
print(f"prime factor of {nums}:==>",factor)

prime_factor(13195)

[455.0,1015.0,1885.0,2639.0] 素因子13195:==&gt; [29.0,13.0,7.0,5.0]