我试图通过传递int.MaxValue
代替1000来测试Problem 1 projecteuler.net的三种解决方案的效果。
第一个解决方案:
long sum = SumDivisibleBy(3) + SumDivisibleBy(5) - SumDivisibleBy(15);
Console.WriteLine(sum);
SumDivisibleBy是:
public static long SumDivisibleBy(int k, int n = int.MaxValue)
{
long m = n / k;
return k * (m * (m + 1) / 2);
}
比
更快(约27秒)第二个解决方案:
long sum = 0;
for (int i = 0; i < int.MaxValue; i++)
{
if (i % 3 == 0 || i % 5 == 0)
{
sum += (long)i;
}
}
Console.WriteLine(sum);
第三个解决方案(我认为这是一个优雅的解决方案)是:
Console.WriteLine(Enumerable.Range(1, 999)
.Where(x => x % 3 == 0 || x % 5 == 0)
.Sum());
但我无法达到此目的(用于测试性能目的):
Console.WriteLine(Enumerable.Range(1, int.MaxValue)
.Where(x => x % 3 == 0 || x % 5 == 0)
.Sum());
因为OverflowException
的性质,它给了我一个int Sum(this IEnumerable<int> source)
是自然的。
我的问题是:
如何在下面的代码中将int Sum(this IEnumerable<int> source)
转发到long Sum(this IEnumerable<long> source)
:
Console.WriteLine(Enumerable.Range(1, int.MaxValue)
.Where(x => x % 3 == 0 || x % 5 == 0)
.Sum());
答案 0 :(得分:2)
尝试将过滤的整数序列投影到一系列long:
.Where(x => x % 3 == 0 || x % 5 == 0)
.Select(x => (long)x)
.Sum()
请注意,.Cast<long>()
看起来更优雅,但won't work for this kind of conversion。
答案 1 :(得分:2)
您可以扩展Enumerable
类,如下所示:
public static class MyExtensions
{
public static IEnumerable<long> Range(long start, long count)
{
for (long i = start; i < start + count; i++)
{
yield return i;
}
}
}
通过这种方式,您可以使用Sum
方法,而不会出现任何问题,如下所示:
MyExtensions.Range(1, int.MaxValue)
.Where(x => x % 3 == 0 || x % 5 == 0)
.Sum());
答案 2 :(得分:0)
仅供参考......我测试了所有推荐的解决方案(LinqPad)并检查了执行时间。
方法1)转换选择 - 时间: 1:23.360s (中)
.Select(x => (long)x)
方法2)扩展方法 - 时间: 02:06.768s (慢)
MyExtensions.Range(1, int.MaxValue)
.Where(x => x % 3 == 0 || x % 5 == 0)
.Sum());
Enumerable.Range(1, int.MaxValue).Where(x=> x%3==0 || x%5==0).Sum(x=>(long)x);
<强> 结论: 强>
每种方法都比你的 SumDivisibleBy 函数慢得多,那么除了优雅的代码之外,Linq解决方案的好处是什么呢?没有。
注意:我没有在内存使用,CPU使用率等其他方面进行测试。