C#试验师 - 前n个素数。逻辑错误?

时间:2015-11-15 11:27:30

标签: c#

在课程中,问题是列出前n个素数。显然,我们应该实施试验划分,同时在阵列中保存素数以减少所需的划分数量。最初我误解了,但是使用一个单独的函数来测试primality得到了一个更慢的解决方案,但是我想按照我应该的方式实现它。

以下是我的尝试,删除了不相关的代码,例如输入测试。

using System;
namespace PrimeNumbers
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Console.Write("How many primes?\n");
            string s = Console.ReadLine();
            uint N;
            UInt32.TryParse(s, out N)
            uint[] PrimeTable = new uint[N];
            PrimeTable[0] = 2;
            for (uint i=1; i < N; i++)//loop n spaces in array, [0] set already so i starts from 1
            {
                uint j = PrimeTable[i -1] + 1;//sets j bigger than biggest prime so far
                bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
                while (!isPrime)//so loop continues until a break is hit
                {
                    isPrime = true;//to ensure that the loop executes
                    for(uint k=0; k < i; k++)//want to divide by first i primes
                    {
                        if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
                        if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
                        {
                            isPrime = false;
                            break;
                        }
                    } 
                    j++;//j increment mentioned above
                }
                PrimeTable[i] = j; //not different if this is enclosed in brace above
            }
            for (uint i = 0; i < N; i++)
                Console.Write(PrimeTable[i] + " ");
            Console.ReadLine();
        }
    }
}

我的评论是我尝试描述我认为代码正在做什么,我尝试了很多小的改动,通常它们会导致在运行时除以零错误,所以我在测试中添加了,但我不认为应该是必要的。 (当我尝试改变循环条件时,我也遇到了几个超出范围的错误。)

我已经看过堆栈交换的几个问题,特别是: Program to find prime numbers 第一个答案使用了不同的方法,第二个答案接近我想要的,但确切的事情是尼克拉尔森的评论:

  

你可以通过跟踪素数来加快速度   试图除以那些。

此处未显示C#:http://rosettacode.org/wiki/Sequence_of_primes_by_Trial_Division#Python

我已经看到了很多其他的方法和算法,比如Eratosthenes sieve和GNF,但实际上只想用这种方式实现它,因为我认为我的问题在于程序逻辑,我不明白为什么它没有'工作。感谢

2 个答案:

答案 0 :(得分:2)

以下内容可以解决您的问题:

    for (uint i = 1; i < numberOfPrimes; i++)//loop n spaces in array, [0] set already so i starts from 1
    {
        uint j = PrimeTable[i - 1] + 1;//sets j bigger than biggest prime so far

        bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
        while (!isPrime)//so loop continues until a break is hit
        {
            isPrime = true;//to ensure that the loop executes
            for (uint k = 0; k < i; k++)//want to divide by first i primes
            {
                if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
                if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
                {
                    isPrime = false;
                    j++; 

                    break; 
                }
            }

        }
        PrimeTable[i] = j; 
    }

我所做的主要改变是将变量j的增量移到条件素数检查中。这是因为,当前值不是素数,所以我们要检查下一个素数,并且必须在中断循环之前移动到下一个候选者。

检查完成后,您的代码正在递增。这意味着当你找到一个主要候选人时,你会增加到下一个候选人并将其指定为你的素数。例如,当j = 3时,它将通过条件,isPrime仍然= true,但是然后j ++会将它增加到4并将它添加到PrimeTable。

有意义吗?

答案 1 :(得分:1)

这可能不是你问题的一个很好的答案,但你可能想看一下这个实现,看看你是否可以发现你的不同之处。

int primesCount = 10;
List<uint> primes = new List<uint>() { 2u };
for (uint n = 3u;; n += 2u)
{
    if (primes.TakeWhile(u => u * u <= n).All(u => n % u != 0))
    {
        primes.Add(n);
    }
    if (primes.Count() >= primesCount)
    {
        break;
    }
}

这正确有效地计算了第一个primesCount素数。