2009-10-17 106 views
2

我在Project Euler中遇到了這個問題。在C#中查找斐波那契數列。 [歐拉練習項目]

這裏的問題問什麼:

在Fibonacci序列中的每個新名詞是通過將前兩個方面產生。從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(); 
} 
+0

參見:http://stackoverflow.com/questions/406446/refactoring-fibonacci-algorithm – 2009-10-17 07:41:53

+0

因爲問題只希望偶而言,需要注意的格局:(O-對於奇, E-for-Even),OEOOEOOEOOEOOE ...你可以修改你的fib-generator來立即返回偶數條件而不需要測試%2。 – abelenky 2009-10-17 16:49:20

回答

9

一個C#中的有趣的功能之一是「屈服」的關鍵字,這是這種東西非常有用:

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); 

「傳統」的遞歸斐波那契實現是這裏有問題的,因爲它扔掉所有沿着最後一個要求的期限完成工作。你將不得不在一個循環中一遍又一遍地撥打這樣的功能,這將複製很多工作,或者你可以與執行開始,並添加參數的遞歸函數來建立所需的總和結果作爲最終計算斐波納契項。我更喜歡這一點,因爲它仍然是一個通用Fibonacci序列的核心,而不是你必須重寫或專門化。

另一種方法是使用傳統實現中的事件(委託)在每個術語完成時調用單獨的方法,但由於我仍然更喜歡迭代器方法,因此我將讓委託選項成爲讀者的練習。

+0

很棒的回答。我認爲你應該在Fibonacci()中改變int i。TakeWhile(i => i <4000000)。Where(i%2 == 0)to int i在Fibonacci()。TakeWhile(i => i <4000000)。在哪裏(我=> i%2 == 0) – 2010-08-04 01:49:04

+0

太棒了。這實際上是斐波那契範圍解決方案的最佳方法:http://ilyatereschuk.blogspot.com/2013/12/blog-post.html – 2013-12-24 07:01:27

1

你檢查在每次迭代都ab。這意味着你幾乎所有的東西都會重複計算。

編輯:

好吧,我看到您的更新。這是非常基本的調試,你應該學會自己嘗試。想想當你的循環條件停止爲真時,ab的值是什麼。

+0

感謝您的反饋。我刪除了B變量的檢查。所以我只檢查A是否是偶數。儘管如此,我仍然得到了錯誤的答案。我不知道什麼可能是錯的。 – 2009-10-17 00:18:58

+0

我支持@ recursive的編輯,我想補充一點,你應該在整個循環中檢查'Container'的值。 – 2009-10-17 00:38:01

1

我認爲這個問題的意思是說你會把所有的偶數加在一起,而序列中的數字不會超過四百萬,這意味着你會增加3,999,992。

+0

「這意味着您將添加3,999,992。」你可以擴展這個嗎?添加3,999,992什麼? – 2009-10-17 02:28:31

1

喬爾,我寫了一個非常類似的代碼;我反正張貼:

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()); 
3
int sum = 2; 
for(int f1 = 1, f2 = 2, f3 = 0; !((f3 = (f1 + f2)) > 4000000); f1 = f2, f2 = f3) 
    sum += f3 * (~f3 & 1); 
5

你的問題不在於你的代碼中包含的錯誤;你的問題是你的代碼包含一個錯誤,你不知道如何找到它。首先解決第二個問題,然後當你有一個錯誤時,你不需要問我們,你可以自己找到它。

學習如何發現錯誤很難,需要大量的練習。以下是我將如何解決這個問題。

我首先將問題簡化到我可以自己做的事情。而不是「甚至不超過400萬的偶數纖數的總和是多少?「我會問」什麼是不超過40的均勻纖維數量的總和?「這很容易手工操作 - 2 + 8 + 34 = 44.

現在在調試器中運行您的程序,通過各行加強,並看到哪裏出問題請問您的程序實際上加起來2,8和34如果是這樣,它得到正確的結果

0

更爲棘手的方式:??

//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

0

這裏是找到斐波那契數字的好方法。

IEnumerable<BigInteger> Fibs() 
{ 
    for(BigInteger a = 0,b = 1;;b = a + (a = b)) 
     yield return b; 
} 
0
 // 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]); 
     }