2

我在stackoverflow上遇到了这个问题:

“我在Project Euler中遇到了这个问题。问题是这样的:斐波那契数列中的每个新项都是通过添加前两项来生成的。从 1 和 2 开始,前 10 个项将是: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 求序列中所有不超过四百万的偶数项之和。”

最佳答案是这个(在 VS2010 中没有为我编译......为什么?):

    IEnumerable<int> Fibonacci()
    {
        int n1 = 0;
        int n2 = 1;

        yield return 1;
        while (true)
        {
          int n = n1 + n2;
          n1 = n2;
          n2 = n;
          yield return n;
        }
    }

    long result=0;

    foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i % 2 == 0))
    {
        result+=i;
    }
    Console.WriteLine(result);

我决定在寻找答案之前自己尝试一下并想出了这个(请告诉我为什么或为什么不是解决这个问题的好方法或坏方法):

我在课堂上写了它,因为将来我可以在课堂上添加更多内容,而不仅仅是解决单个斐波那契问题。

class Fibonacci
{
    private int prevNum1 = 1;
    private int prevNum2 = 2;
    private int sum = 0;

    public int GetSum(int min, int max)
    {
        prevNum1 = min;
        prevNum2 = prevNum1 + prevNum1;
        if (prevNum1 % 2 == 0)
        {
            sum += prevNum1;
        }
        if (prevNum2 % 2 == 0)
        {
            sum += prevNum2;
        }
        int fNum = 0;
        while (prevNum2 <= max)
        {
            fNum = prevNum1 + prevNum2;
            if (fNum % 2 == 0)
            {
                //is an even number...add to total
                sum += fNum;
            }
            prevNum1 = prevNum2;
            prevNum2 = fNum;

        }

        return sum;
    }

}

        Fibonacci Fib = new Fibonacci();
        int sum = Fib.GetSum(1, 4000000);

        Console.WriteLine("Sum of all even Fibonacci numbers 1-4,000,000 = {0}", sum);

同样,我正在寻找关于为什么这是解决此问题的好方法或坏方法的答案。还有为什么第一个解决方案无法编译。我是一个初级程序员,正在努力学习。谢谢!

4

2 回答 2

3

有了这个,它必须编译:

foreach (int i in Fibonacci().TakeWhile(i => i < 4000000).Where(i => i % 2 == 0))
{
    result += i;
}

代码没有编译的问题是糟糕的 lambda 表达式,它是:

.Where(i % 2 == 0)

但必须是

.Where(i => i % 2 == 0)
于 2012-08-08T01:29:12.493 回答
2

由于这一行,代码无法编译:

foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i % 2 == 0))

首先, .Where() 是一种扩展方法(google it),可以在集合上调用(如本例中的整数 IEnumerable)。它返回另一个集合,其中包含满足某些条件的任何元素。

注意 .Where() 的参数是一个产生布尔值的表达式,真或假。

i % 2 == 0

.Where() 不接受 bool 作为参数,在这种情况下,适当的参数是类型

Func<int,bool>

这基本上意味着一个以 int 作为参数并返回 bool 的函数。你可以很简单地定义这些

// defines a function taking an int, returning true if that int is even
Func<int,bool> foo = i => i % 2 == 0

所以在这种情况下使用 .Where() 的正确方法是

foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i => i % 2 == 0))

所以你可以看到 .Where() 接受我们提供的函数并将其应用于每个数字,返回一个偶数集合。

yield 关键字还有一些其他的神奇之处,请随时用谷歌搜索,但它更像是一个高级主题。

于 2012-08-08T01:38:48.383 回答