当前位置:  开发笔记 > 编程语言 > 正文

查找数字的最大素数因子的算法

如何解决《查找数字的最大素数因子的算法》经验,为你挑选了5个好方法。

计算数字中最大素因子的最佳方法是什么?

我认为效率最高的是以下内容:

    找到干净分配的最低素数

    检查除法结果是否为素数

    如果没有,找到下一个最低点

    转到2.

我基于这个假设,因为它更容易计算小的素因子.这是对的吗?我应该研究哪些其他方法?

编辑:我现在已经意识到,如果有超过2个素因子,我的方法是徒劳的,因为当结果是两个其他素数的乘积时,步骤2失败,因此需要递归算法.

再次编辑:现在我已经意识到这仍然有效,因为最后找到的素数必须是最高的,因此对步骤2的非素数结果的任何进一步测试都会导致较小的素数.



1> Triptych..:

这是我所知道的最好的算法(在Python中)

def prime_factors(n):
    """Returns all the prime factors of a positive integer"""
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        d = d + 1

    return factors


pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list

上述方法在O(n)最坏的情况下运行(当输入是素数时).

编辑:
以下是O(sqrt(n))评论中建议的版本.这是代码,再一次.

def prime_factors(n):
    """Returns all the prime factors of a positive integer"""
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        d = d + 1
        if d*d > n:
            if n > 1: factors.append(n)
            break
    return factors


pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list


很容易使它成为O(sqrt(n)),你只需在d*d> n时停止循环,如果此时n> 1,那么它的值应该附加到素因子列表中.
在投票之前请阅读和/或运行此代码.它工作正常.只需复制并粘贴即可.由于写入的prime_factors(1000)将返回[2,2,2,5,5,5],这应该被解释为2 ^ 3*5 ^ 3,也就是素数因子分解.
"在最坏的情况下,在'O(sqrt(n))`中运行" - 不,在最坏的情况下它运行在`O(n)`(例如当`n`是素数时).
因为2是唯一的偶数素数,所以不是每次加1,而是可以单独迭代d = 2,然后将其递增1,然后从d = 3开始,你可以递增2.所以它会减少数量迭代...... :)
这有名字吗?
@avi诀窍是要意识到因为这个循环从第一个素数开始(d = 2)并且去除了所有因子,如果n%d == 0,d将永远是素数.说n = 120. 120的素因子是2 ,2,2,3,5.因此,当d = 2时,(而n%d == 0)从数字中删除所有2,并且你留下了一些其他素因子.关键思想是那些素数因子将大于2.另一个很酷的部分是循环终止于sqrt(n),因为不能有任何大于sqrt(n)的素因子.
这种算法非常低效.而且它是O(sqrt(n))的说法具有误导性:对于诸如整数分解之类的问题,习惯上测量*输入数字*的数量的复杂性,而不是输入的大小.给定输入n具有m = log(n)个数字,该算法的复杂度为O(exp(m/2)).
@avi或其他任何仍然困惑的人:另一种想到它的方法是:最小的除数永远是素数.以12为例.2是最小的除数.然后请注意,所有素数列表彼此相等将等于总数.所以我们知道2是素数.所以我们可以将12除以2 = 6.我们知道其余的素数相互乘以必须等于6.卢卡斯很好地解释了其余的.
我确实认为这是行不通的,也不会检索主要因素,但最终会得到因素。在此代码中的哪里使用质数?d仅是自然数,没有素数。
@Forethinker我想你会称这种方法为"试验部门"或"暴力部队".
效率低下,但它对我的目的来说效果很好.但它可以返回实数(199.0)而不是整数(199).简单修复:用n // = d替换n/= d.

2> Artelius..:

实际上,有几种更有效的方法可以找到大数字的因子(对于较小的因子,试验分工合理地工作得很好).

如果输入数字具有非常接近其平方根的两个因子,则一种非常快的方法称为费马因子分解.它利用身份N =(a + b)(a - b)= a ^ 2 - b ^ 2,易于理解和实现.不幸的是,它一般不是很快.

最常见的分解数字长达100位的方法是Quadratic筛.作为奖励,部分算法可以通过并行处理轻松完成.

我听说的另一种算法是Pollard的Rho算法.它一般不如Quadratic Sieve效率高,但似乎更容易实现.


一旦你决定如何将一个数字分成两个因子,这里是我能想到的最快的算法,找到一个数字的最大素数因子:

创建一个最初存储号码本身的优先级队列.每次迭代,您从队列中删除最高的数字,并尝试将其分成两个因子(当然,不允许1成为这些因素之一).如果此步骤失败,则数字为素数,您就有了答案!否则,将两个因子添加到队列中并重复.


Pollard rho和椭圆曲线方法比二次筛更能摆脱数量的小素因子.无论数量多少,QS都有相同的运行时间.哪种方法更快取决于您的号码是多少; QS将更快地破解难以通过的数字,而rho和ECM将更快地破解易于因素的数字.

3> sundar - Rei..:

我的答案是基于Triptych的,但在其上有很大的改进.它基于超过2和3的事实,所有素数都是6n-1或6n + 1的形式.

var largestPrimeFactor;
if(n mod 2 == 0)
{
    largestPrimeFactor = 2;
    n = n / 2 while(n mod 2 == 0);
}
if(n mod 3 == 0)
{
    largestPrimeFactor = 3;
    n = n / 3 while(n mod 3 == 0);
}

multOfSix = 6;
while(multOfSix - 1 <= n)
{
    if(n mod (multOfSix - 1) == 0)
    {
        largestPrimeFactor = multOfSix - 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }

    if(n mod (multOfSix + 1) == 0)
    {
        largestPrimeFactor = multOfSix + 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }
    multOfSix += 6;
}

我最近写了一篇博客文章,解释了这个算法的工作原理

我敢说,一种不需要进行素数测试(并且没有筛子构造)的方法比使用那些方法的方法运行得更快.如果是这种情况,这可能是这里最快的算法.


你甚至可以进一步理解这个想法,例如超过2,3,5所有质数都是30n + k(n> = 0),其中k只取1到29之间不能被2,3整除的值或5,即7,11,13,17,19,23,29.你甚至可以在你发现的每一个素数之后动态调整到2*3*5*7*...*n + k,其中k不能被任何这些素数整除(注意并非所有可能的k都需要是素数,例如210n + k你必须包括121,否则你会错过[331](http://www.wolframalpha.com/input/?i=isprime%202*3*5*7%2B11^ 2数据集=))
我想它应该是`while(multOfSix - 1 <= n)`

4> Vlad Bezden..:

JavaScript代码:

'option strict';

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

用法示例:

let result = largestPrimeFactor(600851475143);

这是代码示例:



5> Ugnius Malūk..:

类似于@Triptych的答案,但也有所不同。在此示例中,不使用列表或字典。代码是用Ruby编写的

def largest_prime_factor(number)
  i = 2
  while number > 1
    if number % i == 0
      number /= i;
    else
      i += 1
    end
  end
  return i
end

largest_prime_factor(600851475143)
# => 6857

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有