【发布时间】:2012-01-15 00:40:22
【问题描述】:
为了解决Euler Project problem n°5,我写了如下程序:
class p5
{
const int maxNumber = 20;
static void Main(string[] args)
{
Job(); // First warm-up call to avoid Jit latency
var sw = Stopwatch.StartNew();
var result = Job();
sw.Stop();
Debug.Assert(result == 232792560);
Console.WriteLine(result);
Console.WriteLine(sw.Elapsed);
Console.ReadLine();
}
private static int Job()
{
var result = Enumerable.Range(1, int.MaxValue - 1)
.Where(
n => Enumerable.Range(maxNumber / 2 + 1, maxNumber / 2).All(c => n % c == 0)
).First();
return result;
}
}
但是,我发现这有点长(17 秒,在释放模式下),即使它正在工作。
有什么可能的优化吗?
仅供参考,我尝试使用AsParallel 方法,但正如预期的那样,工作量太小,上下文切换比收益重(超过 1 分钟):
var result = Enumerable.Range(1, int.MaxValue - 1).AsParallel()
.Where(
n => Enumerable.Range(maxNumber / 2 + 1, maxNumber / 2).All(c => n % c == 0)
).First();
return result;
[编辑]根据马丁的建议,这个版本除以10所用的时间:
private static int Job()
{
var n =2;
bool result;
do
{
result = true;
for (int c = maxNumber / 2; c <= maxNumber; c++)
{
if (n % c > 0)
{
result = false;
break;
}
}
n ++;//= 2;
} while (!result);
return n;
}
[编辑]总结一下我所有的测试,粗略的执行时间:
- 我的第一次实现:20 秒
- 删除了内部 enumerable.Range 调用(由简单的 for 循环替换):3 秒
- 删除了外部和内部枚举。范围调用:1.5 秒
- 只取偶数:(只有循环,没有 enumerable.range):不到 1 秒
- 使用 drhirsch 建议的 Gcd/LCm 欧几里得算法:0.004 毫秒
最新的建议显然是好的答案。我感谢 drhirsch 提出了另一种方法,而不仅仅是简单的循环优化
【问题讨论】: