什么是找到数字最大素数的最佳方法?

时间:2016-02-18 23:10:31

标签: c# primes prime-factoring factors factorization

我是编程的新手,而我的一位朋友建议我应该对项目Euler进行练习以使其更好。我在问题3上遇到了一个问题:

  

“13195的主要因素是5,7,13和29. 600851475143的最大主要因素是什么?”

现在这是我的解决方案:

class Program
{
    static void Main(string[] args)
    {
        long number = 600851475143;
        bool prime = true;

        for (long i = 3; i <= number; i++)
        {
            for (long n = 2; n < i; n++)
            {

                if (i % n == 0)
                {
                    prime = false;
                    break;
                }
            }

            if (prime)
            {
                if (number % i == 0)
                {
                    Console.WriteLine(i);

                }

            }
            prime = true;

        }
        Console.ReadKey();
    }
}

现在,虽然我确实得到了正确的答案(这是6857),但我发现我的方法非常低效。如果您将运行我的代码,您将看到它仍将在超过2分钟之后运行...我的问题是如何为此编写更高效/更快的代码?

4 个答案:

答案 0 :(得分:5)

  

我的问题是如何为此编写更有效/更快的代码?

这是错误的问题。或者说,这是一个不成熟的问题。

要问的正确问题是:

  • 我的程序是否正确?
  • 我的节目组织得很好吗?

快速制作错误的程序使您能够更快地得到错误的答案,这不是一个改进。 更快地制作组织糟糕的程序非常困难,所以先组织好。

让我们开始为您的计划做一个小但非常重要的改进:我们注意到#34;这件事是不是很重要?&#34;可以由助手清楚地表示:

class Program
{
  static bool IsPrime(long i)
  {
    for (long n = 2; n < i; n++)
    {
      if (i % n == 0)
        return false;
    }
    return true;
  }

  static void Main(string[] args)
  {
    long number = 600851475143;
    for (long i = 3; i <= number; i++)
    {
      if (IsPrime(i))
        Console.WriteLine(i);
    }
    Console.ReadKey();
  }
}

看看那里发生了什么。 您的计划突然变得更容易理解。 IsPrime做什么?它会告诉您整数是否为素数。主循环有什么作用?它打印出3和数字之间的所有素数。

现在,重新开始。 该计划的每个部分都是正确的吗?IsPrime给定时,true会返回1,但通常不会被视为素数。 修复错误。您希望辅助方法可靠。 确保您的帮助方法完全按照他们在锡上的说法进行操作。写测试!因为您希望确保在更改这些方法以使其更快时,您不会意外地使它们不正确。

现在我们既有正确又有条理,我们可以开始优化。你能想到让IsPrime更快的方法吗?肯定的是:

  • 我们只需检查i的平方根。 (请注意,n * n <= in <= Sqrt(i)
  • 更快
  • 一旦我们检查了2,我们就不必检查4,6,8 ......

你能想到其他方法让它更快吗?

但关键是妥善整理您的计划。一旦你有一个组织良好的程序,你可以在更高的层次上推理,你可以找到并消除缓慢的部分。

答案 1 :(得分:3)

首先,您使用的算法是为了知道数字是否为素数,效率非常低(order(n2)),您可以改进函数的顺序,返回数字是否为素数

要确定某个数字是否为素数,您需要检查它是否不能被任何小于n的数字整除。

你只需要考虑高达√n的因子,因为如果n可以被某个数p整除,那么n = p×q,因为p≤q,你可以推导出p≤√n。请注意,您正在考虑小于n而不是小于√n的数字因子。

也许这个类似的问题可以帮到你,“下面最大的素数是什么”。

解决问题的最佳方法,正在使用Eratosthenes筛选。 (的 https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

这是使用Erastosthenes筛子的伪代码。

   public int primes(int n) {
     boolean[] isPrime = new boolean[n];
     for (int i = 2; i < n; i++) {
        isPrime[i] = true;
     }
     // Loop's ending condition is i * i < n instead of i < sqrt(n)
     // to avoid repeatedly calling an expensive function sqrt().
     for (int i = 2; i * i < n; i++) {
       if (!isPrime[i]) continue;
       for (int j = i * i; j < n; j += i) {
         isPrime[j] = false;
       }
     }
     int count = 0;
     for (int i = 2; i < n; i++) {
       if (isPrime[i]) count++;
     }

    //return the max prime
    int maxPrime = 1;
    for(int i = 0; i < isPrime.count; i++){
      if(isPrime[i]){
        maxPrime = i;
      }
      return maxPrime;
    }
  }

答案 2 :(得分:1)

我写了一个方法,它将为您提供所有主要因素,以及其中最大的因素。我的代码正在运行,您可以查看它:

public void PrimeFactor1(long n)
{
    List<int> sList = new List<int>();
    long temp = 1;
    for (int i = 2; i <= n; i++)
    {
        if ((n % i) == 0)
        {
            temp = n / i;
            sList.Add(i);
            i = 1;
            n = temp;
        }     
    }
    string arr = string.Join(",", sList.ToArray());
    Console.Write(arr);
    Console.WriteLine(".");
    Console.WriteLine("The Biggest Prime number is: {0}", sList.Max());
}

答案 3 :(得分:0)

如果您要处理许多Project Euler问题,那么您需要很好地实施Eratosthenes筛选。您的Eratosthenes类的两个有用方法是nextPrime(int p)previousPrime(int p),它们分别返回下一个和下一个最低素数。

ETA:伪代码编辑为错误。遗憾。