【问题标题】:Finding Fibonacci sequence in C#. [Project Euler Exercise]在 C# 中查找斐波那契数列。 【欧拉计划练习】
【发布时间】:2010-12-07 13:10:31
【问题描述】:

我在 Project Euler 中遇到了这个问题。

问题是这样问的:

斐波那契数列中的每个新项都是通过添加前两项来生成的。从 1 和 2 开始,前 10 个术语将是: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 求序列中所有不超过四百万的偶数项之和。

到目前为止我的代码:用新代码编辑,但仍然无法正常工作。

static void Main(string[] args)
{
    int a = 1;
    int b = 2;
    int Container = 0;
    int Sum = 0;

    while (b < 4000000)
    {
        if (a % 2 == 0)
        {
            Container += a;
        }

        Sum = a + b;
        a = b;
        b = Sum;
    }

    Container += b;

    Console.WriteLine(Container.ToString());
    Console.ReadLine();
}

【问题讨论】:

  • 因为问题只需要偶数项,请注意模式:(O-for-odd, E-for-Even), OEOOEOOEOOEOOE... 您可以修改您的 fib 生成器以立即返回偶数- 未经测试的术语 %2。

标签: c# fibonacci


【解决方案1】:

C# 中一个有趣的特性是“yield”关键字,它对这类事情非常有用:

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 => i % 2 == 0))
{
    result+=i;
}
Console.WriteLine(result);

“传统的”递归斐波那契实现在这里是有问题的,因为它抛弃了在最后一个请求术语的过程中完成的所有工作。您必须在循环中一遍又一遍地调用这样的函数,这会重复很多的工作,或者您可以从该实现开始并向递归函数添加一个参数以构建所需的计算最终斐波那契项的总和结果。我更喜欢这个,因为它的核心仍然是一个通用的斐波那契序列,而不是你必须重新编写或专门化的序列。

另一种方法是在传统实现中使用事件(委托)在每个学期完成时调用单独的方法,但由于我仍然更喜欢迭代器方法,因此我将委托选项留给读者作为练习。

【讨论】:

【解决方案2】:

您的问题不在于您的代码包含错误;您的问题是您的代码包含错误并且您不知道如何找到它。先解决第二个问题,以后有BUG就不用问了,自己找就好了。

学习如何查找错误很难,需要大量练习。以下是我将如何解决这个问题。

我会先将问题简化为我可以自己解决的问题。而不是“不超过四百万的偶数数字的总和是多少?”我会问“不超过 40 的偶数 fib 数字的总和是多少?”这很容易用手算出来——2 + 8 + 34 = 44。

现在在调试器中运行您的程序,单步执行每一行,看看哪里出了问题。您的程序实际上加起来是 2、8 和 34 吗?如果是这样,它会得到正确的结果吗?

【讨论】:

    【解决方案3】:
    int sum = 2;
    for(int f1 = 1, f2 = 2, f3 = 0; !((f3 = (f1 + f2)) > 4000000); f1 = f2, f2 = f3)
        sum += f3 * (~f3 & 1);
    

    【讨论】:

      【解决方案4】:

      我认为写这个问题是说你会将所有偶数加在一起,而序列中的数字不超过四百万,这意味着你会加 3,999,992。

      【讨论】:

      • "表示您将添加 3,999,992。"你能扩展一下吗?添加 3,999,992 什么?
      【解决方案5】:

      您在每次迭代时都检查ab。所以这意味着你几乎所有东西都在重复计算。

      编辑:

      好的,我看到你的更新了。这是非常基本的调试,您应该真正学会自己尝试。想想当您的循环条件不再为真时,ab 的值是什么。

      【讨论】:

      • 感谢您的反馈。我删除了对 B 变量的检查。所以我只检查 A 是否是偶数。我仍然得到一个错误的答案。我不知道可能出了什么问题。
      • 我支持@recursive 的编辑,我想补充一点,你应该在整个循环中检查Container 的值。
      【解决方案6】:

      Joel,我写了一个非常相似的代码;无论如何我都会发布它:

      static IEnumerable<int> Fibonacci(int maximum)
      {
          int auxiliar = 0;
          int previous = 0;
          int current = 1;
          while (current < maximum)
          {
              auxiliar = previous;
              previous = current;
              current = auxiliar + current;
              yield return current;
          }
      }
      
      Console.WriteLine(Fibonacci(4000000).Where(number => number % 2 == 0).Sum());
      

      【讨论】:

        【解决方案7】:

        比较棘手的方法:

        //1: Allow declaring of recursive functions
        private delegate Func<T, R> FuncRec<T, R>(FuncRec<T, R> f);
        static Func<T, R> RecFunction<T, R>(Func<Func<T, R>, Func<T, R>> f)
        {
            FuncRec<T, R> funcRec = r => t => f(r(r))(t);
            return funcRec(funcRec);
        }
        
        //Define the factorial function
        public static readonly Func<ulong, ulong> Fibonacci 
                = RecFunction<UInt64, UInt64>(fib => n =>
                    (n == 1 || n == 0)
                    ? n
                    : fib(n - 1) + fib(n - 2)); 
        
        //Make a "continous" version
        static IEnumerable<ulong> ContinousFibonacci()
            {
                ulong count = 0;
                while(true)
                {
                    ulong n = Fibonacci(count);
                    count++;
                    yield return n;
                }
            }
        
        //Linq result
        static void Main(string[] args)
            {
        
        
                ulong result = ContinousFibonacci()
                    .TakeWhile(r => r < 4000000)
                    .Where(IsEven)
                    .Aggregate<ulong, ulong>(0,(current, s) => (s + current));
        
                Console.WriteLine(result);
                Console.ReadLine();
        
            }
        

        ///允许人们创建上述递归函数的Functional-Style方法是由Bart De Smet提出的。见http://bartdesmet.net/blogs/bart/archive/2009/11/08/jumping-the-trampoline-in-c-stack-friendly-recursion.aspx

        【讨论】:

          【解决方案8】:

          这是查找斐波那契数的好方法。

          IEnumerable<BigInteger> Fibs()
          {
              for(BigInteger a = 0,b = 1;;b = a + (a = b))
                  yield return b;
          }
          

          【讨论】:

            【解决方案9】:
                 // count(user input) of Fibonacci numbers   
                    int[] array = new int[20];
                    array[0] = 0;
                    array[1] = 1;
            
                    Console.WriteLine(array[0] + "\n" + array[1]); 
            
                    for (int i = 2; i < 20; i++)
                    {
                        array[i] = array[i - 1] + array[i - 2];
                        Console.WriteLine(array[i]); 
                    }
            

            【讨论】:

              猜你喜欢
              • 2013-02-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-01-17
              • 2018-05-30
              • 1970-01-01
              • 2020-01-18
              • 1970-01-01
              相关资源
              最近更新 更多