【问题标题】:What's a more efficient way to find sum of prime numbers?找到素数和的更有效方法是什么?
【发布时间】:2020-10-29 14:29:02
【问题描述】:

我正在开发一个程序,该程序跟踪将所有素数的总和达到某个数字所需的时间,并试图找到获得该值的最有效方法,因为我有一个秒表(System.Diagnostics) 跟踪需要多长时间。目前,我可以使用以下代码在大约 33-34 秒内找到最多 40,000 的所有素数的总和:

private void ListThePrimes()
        {
            prime = false;
            while (primes < 30000)
            {
                for (int i = 2; i < n; i++)
                {

                    output = n % i;
                    if (output == 0)
                    {
                        primeNum = i;
                        prime = false;
                        break;
                    }
                    else
                    {
                        prime = true;
                    }
                }
                if (prime == true)
                {
                    sum += primeNum;
                    primes++;
                }
                n++;
            }
        }

但是,我觉得有一种方法可以更有效地编写此代码,因为我的目标是在相同的时间内使用更高的数字(例如 200,000 左右)。这是我的秒表代码,如果需要,我会在单击按钮时执行:

    var timer = new Stopwatch();
            timer.Start();
            ListThePrimes();
            timer.Stop();
            TimeSpan timeTaken = timer.Elapsed;
            string foo = timeTaken.ToString(@"m\:ss\.fff");
            MessageBox.Show("The sum is " + sum + ". It took this program " + foo + " seconds to run.");

如果有人能告诉我是否有更有效的方法来执行此操作,我们将不胜感激。

【问题讨论】:

  • 查找“Erathostenes sieve”

标签: c# algorithm primes


【解决方案1】:

您需要优化获取素数的方式,这种方式效率极低。这样做的常用方法是使用Sieve of Eratosthenes。使用这种方法,我可以在几毫秒内轻松获得最多 100000 的所有素数。除此之外,对它们求和是微不足道的。

var n = 100000;
var a = Enumerable.Range(0,n+1).Select(_ => true).ToArray();

for(var i=2;i<Math.Sqrt(n);i++)
{
    if(a[i])
    {
        for(var j = i*i;j<=n;j += i)
        {
            a[j] = false;
        }
    }
}

var result = a.Select( (x,i) => new {IsPrime = x,Prime = i})  
              .Where(x => x.IsPrime && x.Prime > 1) 
              .Sum(x => x.Prime);
    
Console.WriteLine(result);

现场示例:https://dotnetfiddle.net/eBelZD

【讨论】:

  • 从来不知道这存在。我会尽快试用并告诉您效果如何,谢谢!
  • @InsaneProgrammer 我很好奇,所以根据你的问题 dotnetfiddle.net/EQaLiL 的所有素数总和不超过 40,000 - 6.6 毫秒 :) 在我相当多的机器上本地 - 3.2 毫秒
【解决方案2】:

你真的必须研究你的素数方法。一种新方法是 Erathostenes 筛子,但您当前的代码也可以改进很多。

  1. 去掉输出等不必要的变量,直接放在if标签中即可。
  2. 你可以检查一半的数字,因为素数只能是奇数,所以不要做 n++,而是 n+=2;。

【讨论】:

    猜你喜欢
    • 2022-01-07
    • 1970-01-01
    • 2010-10-05
    • 2018-10-20
    • 1970-01-01
    • 2019-01-06
    • 2016-11-03
    • 2019-03-05
    • 2016-05-29
    相关资源
    最近更新 更多