仅使用奇数计算素数需要比奇数和偶数更长

时间:2014-08-10 22:38:33

标签: c# iteration

我正在进行Project Euler挑战并解决了它。然后一位朋友建议我只将潜在素数与已知素数进行比较。他的解决方案大约有一半时间完成。

我回去做了一个新的方法,只计算奇数作为潜在的素数(i + = 2),但它比i ++需要更长的时间。 (我在发布模式下运行)任何人都可以解释原因吗?

这里是c#控制台应用的link

结果如下:

enter image description here

以下是代码:

public class Program
{
    private static int PrimeNumbersCount = 0;
    private static int PrimeNumber = 10001;
    private static List<int> Primes ; 

    static void Main(string[] args)
    {
        Reset();

        DoIt(MichaelsWay);
        DoIt(NelsonsWay);
        DoIt(OurWay);

        Console.ReadLine();
    }

    private static void DoIt(Func<int> WhosWay)
    {
        DateTime start = DateTime.Now;
        int i = WhosWay();
        Console.WriteLine(i);
        Console.WriteLine(DateTime.Now - start);
        Reset();
    }

    private static void Reset()
    {
        PrimeNumbersCount = 0;
        InitializePrimes();
    }

    private static void InitializePrimes()
    {
        Primes = new List<int>(new[] {2});
    }

    private static int OurWay()
    {
        // factor in 2 already being done
        PrimeNumbersCount++;
        // end factor in 2

        bool isPrime = true;
        int i;
        int operationsdone = 0;

        for (i = 3; PrimeNumbersCount < PrimeNumber; i+=2)
        {
            if (Primes.Any(j => i % j == 0))
            {
                isPrime = false;
                operationsdone++;
            }

            if (isPrime)
            {
                PrimeNumbersCount++;
                Primes.Add(i);
            }

            isPrime = true;
        }
        Console.WriteLine("Our way operations done: " + operationsdone);
        return i - 2;
    }

    private static int NelsonsWay()
    {
        bool isPrime = true;
        int i;
        int operationsdone = 0;

        PrimeNumbersCount++; //to account for starting the loop at 2

        for (i = 2; PrimeNumbersCount < PrimeNumber; i++)
        {
            if (Primes.Any(j => i%j == 0))
            {
                isPrime = false;
                operationsdone++;
            }

            if (isPrime)
            {
                PrimeNumbersCount++;
                Primes.Add(i);
            }

            isPrime = true;
        }

        Console.WriteLine("Nelson's way operations done: " + operationsdone);
        return i - 1;
    }

    private static int MichaelsWay()
    {
        bool isPrime = true;
        int i;
        int operationsdone = 0;
        int tempPrimeNumber = PrimeNumber + 1;

        for (i = 1; PrimeNumbersCount < tempPrimeNumber; i++)
        {
            for (int j = 2; j < i - 1; j++)
            {
                if (i%j == 0)
                {
                    isPrime = false;
                    operationsdone++;
                    break;
                }
            }

            if (isPrime)
                PrimeNumbersCount++;

            isPrime = true;
        }

        Console.WriteLine("Michael's way operations done: " + operationsdone);
        return i - 1;
    }
}

2 个答案:

答案 0 :(得分:1)

我会猜测:

您只需拨打重置(),在开头清除列表Primes

您首先执行NelsonsWay,填充列表。 然后执行OurWay,将项目附加到同一列表中。

了解List<T>将所有项目存储在一个连续的数组中。如果您已填充此数组,然后尝试添加另一个项目,则List必须分配一个新的更大的空间块,并将所有现有项目复制到此新内存空间。此分配所花费的时间长度将与列表的当前大小成比例。

因此,如果您不断将项目添加到同一列表中,则性能会随着大小的增加而恶化。

Primes.Add(...)NelsonsWay移除行OurWay,您会看到OurWay确实运行得更快。

答案 1 :(得分:0)

在alu中,增加命令(i ++)需要一个时钟脉冲,但是当你使用求和功能时需要两个CP(在旧系统中它可能需要三个CP)