我正在进行Project Euler挑战并解决了它。然后一位朋友建议我只将潜在素数与已知素数进行比较。他的解决方案大约有一半时间完成。
我回去做了一个新的方法,只计算奇数作为潜在的素数(i + = 2),但它比i ++需要更长的时间。 (我在发布模式下运行)任何人都可以解释原因吗?
这里是c#控制台应用的link。
结果如下:
以下是代码:
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;
}
}
答案 0 :(得分:1)
我会猜测:
您只需拨打重置(),在开头清除列表Primes
。
您首先执行NelsonsWay
,填充列表。
然后执行OurWay
,将项目附加到同一列表中。
了解List<T>
将所有项目存储在一个连续的数组中。如果您已填充此数组,然后尝试添加另一个项目,则List必须分配一个新的更大的空间块,并将所有现有项目复制到此新内存空间。此分配所花费的时间长度将与列表的当前大小成比例。
因此,如果您不断将项目添加到同一列表中,则性能会随着大小的增加而恶化。
从Primes.Add(...)
和NelsonsWay
移除行OurWay
,您会看到OurWay
确实运行得更快。
答案 1 :(得分:0)
在alu中,增加命令(i ++)需要一个时钟脉冲,但是当你使用求和功能时需要两个CP(在旧系统中它可能需要三个CP)