简体   繁体   English

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

[英]efficient ways of finding the largest prime factor of a number

I'm doing this problem on a site that I found (project Euler), and there is a question that involves finding the largest prime factor of a number. 我在我找到的网站上做了这个问题(项目Euler),并且有一个问题涉及找到一个数字的最大素数因子。 My solution fails at really large numbers so I was wondering how this code could be streamlined? 我的解决方案失败了很多,所以我想知道如何简化这段代码?

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

it fails when using large numbers, which is the point of the question I guess. 使用大数字时失败,这是我猜的问题。 (computer jams, tells me I have run out of memory and asks me which programs I would like to stop). (计算机堵塞,告诉我我的内存已用完,并询问我想停止哪些程序)。

************************************ thanks for the answer. ************************************谢谢你的回答。 there was actually a couple bugs in the code in any case. 在任何情况下,代码中都存在一些错误。 so the fixed version of this (inefficient code) is below. 所以这个(效率低下的代码)的固定版本如下。

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

From your approach you are first generating all divisors of a number n in O(n) then you test which of these divisors is prime in another O(n) number of calls of test_prime (which is exponential anyway). 从你的方法开始,你首先在O(n)生成一个数n所有除数,然后在另一个O(n)次调用test_prime (无论如何都是指数)中测试这些除数中的哪一个是素数。

A better approach is to observe that once you found out a divisor of a number you can repeatedly divide by it to get rid of all of it's factors. 更好的方法是观察一旦你发现一个数字的除数,你可以反复除以它来摆脱所有这些因素。 Thus, to get the prime factors of, say 830297 you test all small primes (cached) and for each one which divides your number you keep dividing: 因此,为了获得主要因素,例如830297你测试所有小素数(缓存),并且对于每个分割你的数字的你应该继续划分:

  • 830297 is divisible by 13 so now you'll test with 830297 / 13 = 63869 830297可被13整除,所以现在你将用830297 / 13 = 63869测试
  • 63869 is still divisible by 13 , you are at 4913 63869仍可被13整除,你是4913
  • 4913 doesn't divide by 13, next prime is 17 which divides 4913 to get 289 4913不除以13,下一个素数是17 ,它将4913除以得到289
  • 289 is still a multiple of 17 , you have 17 which is the divisor and stop. 289仍然是17的倍数,你有17这是除数和停止。

For further speed increase, after testing the cached prime numbers below say 100 , you'll have to test for prime divisors using your test_prime function (updated according to @Ben's answer) but go on reverse, starting from sqrt . 为了进一步提高速度,在测试了低于100的缓存素数后,你将不得不使用test_prime函数测试素数除数(根据@ Ben的答案更新),但是从sqrt开始反向。 Your number is divisible by 71 , the next number will give an sqrt of 91992 which is somewhat close to 6857 which is the largest prime factor. 您的数字可以被71整除,下一个数字将给出91992sqrt ,这有点接近6857 ,这是最大的主要因素。

Here is my favorite simple factoring program for Python: 这是我最喜欢的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

The basic algorithm is trial division, using a prime wheel to generate the trial factors. 基本算法是试验划分,使用素轮产生试验因子。 It's not quite as fast as trial division by primes, but there's no need to calculate or store the prime numbers, so it's very convenient. 它并不像素数的试验分割那么快,但是没有必要计算或存储素数,所以它非常方便。

If you're interested in programming with prime numbers, you might enjoy this essay at my blog. 如果您对素数编程感兴趣,可以在我的博客上欣赏这篇文章

My solution is in C#. 我的解决方案是在C#中。 I bet you can translate it into python. 我打赌你可以把它翻译成python。 I've been test it with random long integer ranging from 1 to 1.000.000.000 and it's doing good. 我一直用1到1.000.000.000之间的随机长整数来测试它并且它做得很好。 You can try to test the result with online prime calculator Happy coding :) 您可以尝试使用在线主计算器测试结果快乐编码:)

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

The naive primality test can be improved upon in several ways: 可以通过以下几种方式改进幼稚素性测试:

  1. Test for divisibility by 2 separately, then start your loop at 3 and go by 2's 分别用2测试可分性,然后在3开始循环并按2进行
  2. End your loop at ceil(sqrt(num)). 在ceil结束你的循环(sqrt(num))。 You're guaranteed to not find a prime factor above this number 您可以保证找不到超过此数字的主要因素
  3. Generate primes using a sieve beforehand, and only move onto the naive way if you've exhausted the numbers in your sieve. 预先使用筛子生成素数,如果你已经用尽了筛子中的数字,那么只能进入天真的方式。

Beyond these easy fixes, you're going to have to look up more efficient factorization algorithms. 除了这些简单的修复之外,您还必须查找更有效的分解算法。

Use a Sieve of Eratosthenes to calculate your primes. 使用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)

The point to prime factorization by trial division is, the most efficient solution for factorizing just one number doesn't need any prime testing. 通过试验分部进行素数分解的要点是,仅对一个数进行分解的最有效解决方案不需要任何主要测试。

You just enumerate your possible factors in ascending order, and keep dividing them out of the number in question - all thus found factors are guaranteed to be prime. 您只需按升序列举可能的因子,并将它们从有问题的数字中分开 - 所有这些因素都保证是最优的。 Stop when the square of current factor exceeds the current number being factorized. 当当前因子的平方超过被分解的当前数时停止。 See the code in user448810's answer . 请参阅user448810的答案中的代码。

Normally, prime factorization by trial division is faster on primes than on all numbers (or odds etc.), but when factorizing just one number, to find the primes first to test divide by them later, will might cost more than just going ahead with the increasing stream of possible factors. 通常情况下,由审判庭因式分解更快素数比所有的数字(或比值等),但因式分解只是一个号码时,先找到素数由他们后来测试鸿沟, 可能成本比只是走在前面更越来越多的可能因素。 This enumeration is O(n) , prime generation is O(n log log n) , with the Sieve of Eratosthenes (SoE) , where n = sqrt(N) for the top limit N . 该枚举是O(n) ,素数生成是O(n log log n) ,具有Eratosthenes筛选(SoE) ,其中n = sqrt(N)作为上限N. With trial division (TD) the complexity is O(n 1.5 /(log n) 2 ) . 通过试验区(TD),复杂度为O(n 1.5 /(log n) 2

Of course the asymptotics are to be taken just as a guide, actual code's constant factors might change the picture. 当然,渐近线只是作为指导,实际代码的常数因素可能会改变图像。 Example, execution times for a Haskell code derived from here and here , factorizing 600851475149 (a prime): 例如,从这里这里派生的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)

so it depends. 所以这取决于。 Of course factorizing the composite number in question, 600851475143, is near instantaneous, so it doesn't matter there. 当然,对有问题的复合数进行分解,即600851475143,几乎是瞬时的,因此无关紧要。

Here is an example in JavaScript 这是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;
}

I converted the solution from @under5hell to Python (2.7x). 我将解决方案从@ under5hell转换为Python(2.7x)。 what an efficient way! 多么有效的方式!

def largest_prime_factor(num, div=2):
    while div < num:
        if num % div == 0 and num/div > 1:
            num = num /div
            div = 2
        else:
            div = div + 1
    return num
>> print largest_prime_factor(600851475143)
6857
>> print largest_prime_factor(13195)
29

Try this piece of code: 试试这段代码:

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)

Old one but might help 旧的但可能有所帮助

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)

I Hope this would help and easy to understand. 我希望这会有所帮助,也很容易理解。

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)

This code for getting the largest prime factor, with nums value of prime_factor(13195) when I run it, will return the result in less than a second. 这个用于获取最大素数因子的代码,当我运行它时,其值为prime_factor(13195),将在不到一秒的时间内返回结果。 but when nums value gets up to 6digits it will return the result in 8seconds. 但是当nums值达到6digits时,它将在8秒内返回结果。

Any one has an idea of what is the best algorithm for the solution... 任何人都知道解决方案的最佳算法是什么......

def prime_factor(nums): 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) prime_factor(13195)

[455.0, 1015.0, 1885.0, 2639.0] prime factor of 13195:==> [29.0, 13.0, 7.0, 5.0] [455.0,1015.0,1885.0,2639.0]素数因子13195:==> [29.0,13.0,7.0,5.0]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM