C# 生成素数序列,循环中断vs LINQ TakeWhile
我尝试用C#生成素数序列。 到目前为止,代码似乎运行良好C# 生成素数序列,循环中断vs LINQ TakeWhile,c#,linq,primes,C#,Linq,Primes,我尝试用C#生成素数序列。 到目前为止,代码似乎运行良好 List<int> _primes = new List<int>(); bool IsPrime(int num) { if (num < 2) return false; int chkEnd = (int)Math.Sqrt(num); foreach (var p in _primes) { if (p > chkEnd)
List<int> _primes = new List<int>();
bool IsPrime(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
foreach (var p in _primes)
{
if (p > chkEnd)
break;
if (num % p == 0)
return false;
}
return true;
}
for (int i=2; i<1000000; i++)
{
if (IsPrime(i))
_primes.Add(i);
}
List_primes=newlist();
bool IsPrime(整数)
{
if(num<2)
返回false;
int chkEnd=(int)Math.Sqrt(num);
foreach(var p in_素数)
{
如果(p>chkEnd)
打破
如果(num%p==0)
返回false;
}
返回true;
}
对于(int i=2;i x num%p!=0);
}
有人知道吗
编辑: 我将循环迭代次数增加到5000000,在控制台应用程序中运行代码并输出执行时间 00:00:01.1841593——iPrime_PureLoopBreak 00:00:03.2560654——iPrime_TakeWhileAndLoop 00:00:03.4178782——IsPrime_takewhilendall
static void Main(string[] args)
{
List<int> _primes;
bool IsPrime_PureLoopBreak(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
foreach (var p in _primes)
{
if (p > chkEnd)
break;
if (num % p == 0)
return false;
}
return true;
}
bool IsPrime_TakeWhileAndLoop(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
foreach (var p in _primes.TakeWhile(x => x <= chkEnd))
{
if (num % p == 0)
return false;
}
return true;
}
bool IsPrime_TakeWhileAndAll(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
return _primes.TakeWhile(x => x <= chkEnd).All(p => num % p != 0);
}
var t1 = Measure(() =>
{
_primes = new List<int>();
for (int i = 2; i < 5000000; i++)
{
if (IsPrime_PureLoopBreak(i))
_primes.Add(i);
}
});
Console.WriteLine($"{t1} -- IsPrime_PureLoopBreak");
var t2 = Measure(() =>
{
_primes = new List<int>();
for (int i = 2; i < 5000000; i++)
{
if (IsPrime_TakeWhileAndLoop(i))
_primes.Add(i);
}
});
Console.WriteLine($"{t2} -- IsPrime_TakeWhileAndLoop");
var t3 = Measure(() =>
{
_primes = new List<int>();
for (int i = 2; i < 5000000; i++)
{
if (IsPrime_TakeWhileAndAll(i))
_primes.Add(i);
}
});
Console.WriteLine($"{t3} -- IsPrime_TakeWhileAndAll");
Console.ReadLine();
}
public static TimeSpan Measure(Action action)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
action?.Invoke();
stopwatch.Stop();
return stopwatch.Elapsed;
}
static void Main(字符串[]args)
{
列出素数;
bool IsPrime_PureLoopBreak(整数)
{
if(num<2)
返回false;
int chkEnd=(int)Math.Sqrt(num);
foreach(var p in_素数)
{
如果(p>chkEnd)
打破
如果(num%p==0)
返回false;
}
返回true;
}
bool IsPrime_TakeWhileAndLoop(整数)
{
if(num<2)
返回false;
int chkEnd=(int)Math.Sqrt(num);
foreach(var p在_primes.TakeWhile中(x=>x num%p!=0);
}
变量t1=度量(()=>
{
_素数=新列表();
对于(int i=2;i<5000000;i++)
{
if(iPrime_PureLoopBreak(i))
_加上(i);
}
});
WriteLine($“{t1}--IsPrime_PureLoopBreak”);
变量t2=度量(()=>
{
_素数=新列表();
对于(int i=2;i<5000000;i++)
{
if(i优先权)
_加上(i);
}
});
Console.WriteLine($“{t2}--IsPrime_TakeWhileAndLoop”);
变量t3=度量(()=>
{
_素数=新列表();
对于(int i=2;i<5000000;i++)
{
if(i优先权(i))
_加上(i);
}
});
Console.WriteLine($“{t3}--IsPrime_takewhilendall”);
Console.ReadLine();
}
公共静态时间跨度度量(操作)
{
var stopwatch=新秒表();
秒表。开始();
action?.Invoke();
秒表;
返回秒表。已过;
}
使用LINQ有一些额外的开销。您正在创建和调用lambda表达式
但是,在得出结论之前,一定要尝试发布版本。考虑编译器需要生成的代码。“高级”代码(如Linq)简单易写,但编译器通常更难很好地优化 您前面的示例可以进一步简化为使用普通for循环而不是foreach,因此每次迭代只需要少量指令 使用linq时,编译器将为迭代器生成一个代理对象。这需要调用lambda以检查是否需要继续迭代,并且编译器可能无法内联方法调用。方法调用很便宜,但仍然比简单的算术指令贵几倍
因此,根据经验,使用Linq和其他高级模式来提高可读性。如果您发现代码中的某些部分没有达到性能目标,请使用探查器准确地确定哪些部分需要时间,然后重写该部分,直到速度足够快或尽可能快。您有什么问题?“执行时间显著增加”
bool IsPrime(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
return _primes.TakeWhile(x => x <= chkEnd).All(p => num % p != 0);
}
static void Main(string[] args)
{
List<int> _primes;
bool IsPrime_PureLoopBreak(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
foreach (var p in _primes)
{
if (p > chkEnd)
break;
if (num % p == 0)
return false;
}
return true;
}
bool IsPrime_TakeWhileAndLoop(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
foreach (var p in _primes.TakeWhile(x => x <= chkEnd))
{
if (num % p == 0)
return false;
}
return true;
}
bool IsPrime_TakeWhileAndAll(int num)
{
if (num < 2)
return false;
int chkEnd = (int)Math.Sqrt(num);
return _primes.TakeWhile(x => x <= chkEnd).All(p => num % p != 0);
}
var t1 = Measure(() =>
{
_primes = new List<int>();
for (int i = 2; i < 5000000; i++)
{
if (IsPrime_PureLoopBreak(i))
_primes.Add(i);
}
});
Console.WriteLine($"{t1} -- IsPrime_PureLoopBreak");
var t2 = Measure(() =>
{
_primes = new List<int>();
for (int i = 2; i < 5000000; i++)
{
if (IsPrime_TakeWhileAndLoop(i))
_primes.Add(i);
}
});
Console.WriteLine($"{t2} -- IsPrime_TakeWhileAndLoop");
var t3 = Measure(() =>
{
_primes = new List<int>();
for (int i = 2; i < 5000000; i++)
{
if (IsPrime_TakeWhileAndAll(i))
_primes.Add(i);
}
});
Console.WriteLine($"{t3} -- IsPrime_TakeWhileAndAll");
Console.ReadLine();
}
public static TimeSpan Measure(Action action)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
action?.Invoke();
stopwatch.Stop();
return stopwatch.Elapsed;
}