最大素因子算法优化

Posted

技术标签:

【中文标题】最大素因子算法优化【英文标题】:Largest Prime Factor algorithm optimization 【发布时间】:2011-02-09 23:54:29 【问题描述】:

我正在尽我所能改进这个有趣的算法。

现在,我有这个:

using System;

class Program


    static void Main()
    
        ulong num, largest_pFact;
        uint i = 2;
        string strNum;

        Console.Write("Enter number: ");
        strNum = Console.ReadLine();
        num = ulong.Parse(strNum);
        largest_pFact = num;


        while (i < Math.Sqrt((double) largest_pFact))
        
            if (i % 2 != 0 | i == 2) 
                if (largest_pFact % i == 0) 
                    largest_pFact /= i;
            

            i++;
        

        Console.WriteLine("Largest prime factor of 0 is: 1", num, largest_pFact);
        Console.ReadLine();

    

有什么想法吗?

谢谢!

编辑:我实现了 Ben 的算法,感谢大家的帮助!

【问题讨论】:

可能重复 [C#, 找到数字的最大素数](***.com/questions/2535251/…) 你的算法是错误的。 16的最大质因数是多少? 【参考方案1】:

我有一个更快的算法here。

它消除了平方根并正确处理重复因素。

进一步优化:

static private ulong maxfactor (ulong n)

    unchecked
    
        while (n > 3 && 0 == (n & 1)) n >>= 1;

        uint k = 3;
        ulong k2 = 9;
        ulong delta = 16;
        while (k2 <= n)
        
            if (n % k == 0)
            
                n /= k;
            
            else
            
                k += 2;
                if (k2 + delta < delta) return n;
                k2 += delta;
                delta += 8;
            
        
    

    return n;

这是一个工作演示:http://ideone.com/SIcIL

【讨论】:

@Vlad:进一步改进(消除了乘法)。 似乎是这样,但我在上次更新(因为未检查)和第一次更新时遇到了很多错误。 @Vlad: 错字已修复,抱歉 它现在可以工作并且比我的“不完整算法”快得多,谢谢 Ben。 ;)(在我的 20 位数字算法中,搜索大约需要 30 分钟,现在它在不到 3 秒的时间内得到了结果,这真是令人难以置信) @Vlad:小心,ulong 中只有大约 20 位数字...如果它是素数,您的算法可能会溢出 i 并且永远不会完成。这就是真正奇怪的if (k2 + delta &lt; delta) 可以捕捉到的东西。【参考方案2】:

-将 Math.Sqrt((double) maximum_pFact) 存储在某个变量中,最好是一个 ulong。这避免了每次通过循环都重新计算函数,并且整数比较可能比浮点比较快。您需要将比较更改为

- 完全避免在偶数上循环。只需包含 i=2 的特殊情况,然后从 3 处的 i 开始,每次循环递增 2。您可以更进一步,让 i=2,3 成为特例,然后只测试 i = 6n+1 或 6n-1。

【讨论】:

但是只要找到一个因子,平方根就会改变......当然,平方根根本不是必需的。 此时您更新数字 - 额外计算的数量将非常少。虽然我只是试图逐步而不是果断地改进他的算法。【参考方案3】:

好吧,首先我会将特殊情况 2 移出循环,如果可以处理一次,则在整个循环中检查它是没有意义的。如果可能,请使用数据类型 int 而不是 uint,因为它通常更快:

if (largest_pFact % 2 == 0) 
  largest_pFact /= 2;

int i = 3;
while (i < Math.Sqrt((double) largest_pFact)) 
  if (i % 2 != 0) 
    if (largest_pFact % i == 0) 
      largest_pFact /= i;
    
  
  i++;

平方根计算比较昂贵,所以也应该提前完成:

if (largest_pFact % 2 == 0) 
  largest_pFact /= 2;

int i = 3;
int sq = Math.Sqrt((double) largest_pFact);
while (i < sq) 
  if (i % 2 != 0) 
    if (largest_pFact % i == 0) 
      largest_pFact /= i;
    
  
  i++;

然后我会以两步递增i,以消除一次模检查:

if (largest_pFact % 2 == 0) 
  largest_pFact /= 2;

int i = 3;
int sq = Math.Sqrt((double) largest_pFact);
while (i < sq) 
  if (largest_pFact % i == 0) 
    largest_pFact /= i;
  
  i += 2;

为了工作,我相信您需要在循环内使用while 而不是if,否则它将跳过重复的因素:

if (largest_pFact % 2 == 0) 
  largest_pFact /= 2;

int i = 3;
int sq = Math.Sqrt((double) largest_pFact);
while (i < sq) 
  while (largest_pFact % i == 0) 
    largest_pFact /= i;
  
  i += 2;

【讨论】:

很好,但是关于循环外的 sqrt 可能不会更快,因为在它内部每次迭代都会使搜索变小。【参考方案4】:

一方面,您不需要在每次迭代中运行Math.Sqrt

    int root = Math.Sqrt((double) largest_pFact);

    while (i < root)
    
        if ((i % 2 != 0 | i == 2) && largest_pFact % i == 0) 
            largest_pFact /= i;
            root = Math.Sqrt((double) largest_pFact);
        

        i++;
    

【讨论】:

【参考方案5】:

我认为:

生成最多num/2 的素数 然后从最大到最小检查您的num 是否可以被素数整除

会更快。

编辑 num/2 NOT sqrt

【讨论】:

这可能适用于较小的数字,但对于庞大的数字会花费太多。【参考方案6】:

在 sqrt(num) 和 2 之间查找总是比从 num/2 开始要快。每个因子对(除平方根之外)都有一个小于 sqrt(num) 的数字。

例如:对于 15,int(sqrt(15))==3 15/3=5,因此您通过从 3 而不是 7 开始测试来找到“5”因子。

【讨论】:

这是对 damienix 答案的评论?快点得到一些代表,这样你就可以以正确的方式离开 cmets ;)

以上是关于最大素因子算法优化的主要内容,如果未能解决你的问题,请参考以下文章

最大公因子求法

粒子群算法优化PID参数实例

优化覆盖基于matlab蚁群算法求解无线传感器覆盖优化问题含Matlab源码 1835期

12-算法训练 素因子去重

带收缩因子的PSO优化算法

算法训练 素因子去重