【问题标题】:efficient ways of finding the largest prime factor of a number找到一个数的最大素数的有效方法
【发布时间】:2014-08-01 17:17:26
【问题描述】:

我在我找到的一个网站(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)

【问题讨论】:

  • 第一步是将range替换为xrange
  • 这两个函数的逻辑有什么区别?
  • 也检查this thread
  • range(600851475143) 将占用至少 600851475143 x 4 字节的内存。 xrange 不会(假设是 python2)。
  • 如果谈到高效的方式,我建议阅读基础知识,例如。从wiki Integer factorization开始。你这样做的直接方式是运行内存或时间。

标签: python primes prime-factoring factorization


【解决方案1】:

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

更好的方法是观察,一旦你找到一个数的除数,你就可以反复除以它,以消除它的所有因数。因此,要获得素数,比如830297,您需要测试所有小素数(缓存),并且对于每一个除以您的数字的素数,您一直在除:

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

为了进一步提高速度,在测试下面的缓存素数后说100,您必须使用您的test_prime 函数(根据@Ben 的答案更新)测试素数除数,但要反过来,从sqrt。你的数字可以被71整除,下一个数字将给出91992中的sqrt,这有点接近6857,这是最大的素数。

【讨论】:

  • sqrt 开始向下是非常糟糕的建议。
  • 正如@Will 所说,您应该从 2 开始计数; 不要从平方根开始倒数。
  • 对于p*q 的表格数字,其中pq 非常接近。
【解决方案2】:

这是我最喜欢的 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

【讨论】:

    【解决方案3】:

    我的解决方案是 C#。我打赌你可以把它翻译成python。我已经用 1 到 1.000.000.000 的随机长整数对其进行了测试,效果很好。你可以尝试在线测试结果prime calculatorHappy coding:)

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

    【讨论】:

      【解决方案4】:

      朴素素性测试可以通过多种方式改进:

      1. 分别测试能否被 2 整除,然后从 3 开始循环,然后再除以 2
      2. 在 ceil(sqrt(num)) 处结束循环。保证您找不到高于此数字的素因子
      3. 事先使用筛子生成素数,只有在你用尽筛子中的数字时才使用简单的方法。

      除了这些简单的修复之外,您还必须寻找更有效的分解算法。

      【讨论】:

      • 只是对上述 2 的澄清:在 ceil(sqrt(num)) 之上可以有素因数。示例:3*13 = 39, ceil(sqrt(39)) = 7。当然如果你已经找到了 3,那么你可能已经消除了 13。
      【解决方案5】:

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

      【讨论】:

      • 我在 Euler 中使用上面的代码和另一个简单的函数解决了这个问题,它在找到主要因素方面肯定是有效的。 OP的问题标题是“找到素数和因子的有效方法”,我认为我的筛子是有效的。
      • 在这个特定问题中不需要预先计算素数。它“涉及找到一个数字的最大素因数”。标题,你知道...
      • 我主要是后来在 Euler 上发表的,有一个计算素数的好方法肯定会有用,避免使用包含“找到素数的有效方法”的另一个标题。
      【解决方案6】:

      通过试除法进行素数分解的要点是,仅分解一个数的最有效解决方案不需要任何素数测试。

      您只需按升序列举可能的因子,并不断将它们从所讨论的数字中除以 - 所有因此找到的因子都保证是素数。当当前因子的平方超过当前被分解的数字时停止。请参阅user448810's answer 中的代码。

      通常,通过试除法对素数进行素数分解比对所有数字(或赔率等)进行分解要快,但是当仅分解一个数时,要先找到素数然后再测试除法,会 s> 可能花费更多,而不仅仅是随着可能因素的增加而继续前进。这个枚举是O(n),素数生成是O(n log log n),用the Sieve of Eratosthenes (SoE),其中n = sqrt(N) em> 表示上限 N。使用试除法 (TD),复杂度为 O(n1.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 几乎是瞬时的,所以在那里并不重要。

      【讨论】:

      • 你应该发布时间比较和一些代码。看到它会很有趣。
      • @PadraicCunningham 我已经编辑过;你是对的,这取决于代码的细节。
      【解决方案7】:

      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;
      }
      

      【讨论】:

        【解决方案8】:

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

        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
        

        【讨论】:

          【解决方案9】:

          试试这段代码:

          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)
          

          【讨论】:

          • 虽然欢迎使用此代码 sn-p,并且可能会提供一些帮助,但它会是 greatly improved if it included an explanation of howwhy 这解决了问题。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。
          【解决方案10】:

          旧的,但可能有帮助

          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)
          

          【讨论】:

            【解决方案11】:

            我希望这会有所帮助且易于理解。

            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)
            

            【讨论】:

              【解决方案12】:

              此代码用于获取最大素因子,当我运行它时,nums 值为 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的素数:==> [29.0, 13.0, 7.0, 5.0]

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2011-01-15
                • 2014-11-28
                • 2014-11-12
                • 2011-10-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多