2013-12-07 109 views
-3

我試圖使一個C程序,其中所述問題是: X = 4/1 - 4/3 4/5 + - 4/7 + 4/9 ....遞歸碼 - 4/3 4/5 +

時,在前面的交互計算的「x」的價值爲停止條件低於0.0001

#include <iostream> 

using namespace std; 

float recursion(float n){ 

    int f = 0 , i = 1; 
    float calc = 4; 

    f = i%2; 

    if (calc == 0.0001) 
     return 0; 


     if (f != 0){ 
      calc += recursion (4/n) - recursion (4/n+2); 
      n += 2; 
     } 
      else 
       calc += recursion (4/n) + recursion (4/n+2); 
       n+=2; 

      return calc; 
} 
int main(){ 

    float n , result; 

    cout << "Enter the value of N" ; 
    cin >> n; 

    result = recursion (n); 

    cout << "The value of N is ..." << result ; 
} 

我試圖讓一個會計變更標誌「+」到「 - 」或「 - 」到「+」。 我不知道爲什麼codito不工作。歡迎任何幫助

+3

您是否在'else'子句中缺少一組大括號(括號)? – KeithSmith

+1

當達到'if(calc == 0.0001)'時,'calc'總是4,所以它永遠不會導致返回 – fredrik

+0

另外,'i'總是'1',所以'f'也是。 – Johnsyweb

回答

0

見我的評論在線:

float recursion(float n){ 

    int f = 0 , i = 1; 
    float calc = 4; 

    f = i%2; 
    // this if condition will never succeed so you have infinite recursion 
    // so you will end with stack overflow 
    if (calc == 0.0001) 
     return 0; 


    if (f != 0){ 
     calc += recursion (4/n) - recursion (4/n+2); 
     n += 2; 
    } 
     else 
      calc += recursion (4/n) + recursion (4/n+2); 
      n+=2; 

     return calc; 

}

解決你的問題是,你讓函數有兩個參數,第一個參數,因爲它是和第二個參數應該是calc的調用者。

+0

有趣的是,您來到堆棧溢出,詢問堆棧溢出異常:D –

+0

我猜這就是谷歌所說的。 – remus

2

我不認爲遞歸是必要的。這很容易通過迭代來解決。 我看到以下模式。分母是1,3,5,7個奇數。這是我%2。 分數的符號+和 - 之間交替 - 。使用迭代的模數2將當前分數乘以-1。然後+ =到運行總和。

+0

感謝您的幫助,因爲他已經完成了互動,這個問題開始讓我做遞歸,並且我是 –

0
  1. 在這個代碼段:

    int f = 0 , i = 1; 
    float calc = 4; 
    
    f = i%2; 
    

    f是始終爲1。我不知道你想和這個才達到的,但它可能是錯的。

  2. 使用浮點值時避免使用精確比較。由於它們是四捨五入的,所以比較可能會失敗,並且您不知道方法。相反,使用

    if (calc <= 0.0001) 
    
  3. 此外,您計算總和的方式是錯誤的。例如,您不必使用遞歸來計算4/n。

  4. recursion (4/n+2)應該是recursion (4/(n+2)),因爲運算符的優先順序,但無論如何,這是錯誤的形式。

0

因此,執行遞歸問題時的第一步是寫出您的迭代步驟以及您將停止遞歸的條件。

讓我們看一個函數聲明:

float recursion(float n) { ... } 

這聽起來像你的最後一次迭代會當:

(4./n) - (4./(n+2)) < 0.0001 

而且在每一步,它看起來像你想的是delta爲總:

total += (4./n) - (4./(n+2)) 

讓我們開始:

float recursion(int n) { 

    // Calculate the delta at each step... 
    const float delta = (4./n - 4./(n+2)); 

    // If the delta is less than our tolerance, then we __don't__ recurse. 
    // Depending on the requirements of your algorithm, you might return 0 here, 
    // or delta as I have. 
    if (delta < 0.0001) 
     return delta; 

    // Otherwise, we should recurse. 
    return delta + recursion(n+4); 
} 

我們也可以非常容易地將它實現爲循環而不是遞歸。這樣做通常會有助於更清楚地看到迭代過程。

float iterative() { 
    int n = 1; 
    float total = 0; 

    while (true) { 
     // Calculate the delta at each step... 
     const float delta = (4./n - 4./(n+2)); 

     // If the delta is less than our tolerance, then we are done! 
     if (delta < 0.0001) 
      return total + delta; 

     // Otherwise, update the total and keep iterating. 
     total += delta; 
     n += 4; 
    } 
} 

需要注意以下幾點:

  • 在C語言中,你需要小心整數除法與浮點除法。在你的代碼中,你沒事,因爲n是一個浮點數。在我的代碼中,我已將n更改爲整數,所以我使用4.而不是4,因爲編譯器會將其解釋爲double float(也稱爲double),而不是整數。
  • 我每次迭代/遞歸4次。如果你看不出原因,那麼看看每次迭代要完成多少數學計算。
  • 我們只將分母(您名爲n)傳遞給每個遞歸函數。更好地命名變量可以幫助更清楚地說明這一點。
+0

編程領域的一名新學員,感謝您的幫助,因爲他已經完成了交互式的工作,開始了這個問題讓我做遞歸,而且我是編程領域的新生 –

0

你想評估的序列收斂於pi。當你考慮arctan功能的泰勒發展的x=1,因此arctan(1)=pi/4該序列出現了:

arctan

不幸的是這種擴張並沒有收斂速度非常快(認爲所有奇數monoms等於1,所以你正在失去他們的收斂力)。有更好的方法來評估pi的小數。

無論如何,如前所述,遞歸不應該用來解決這類問題。事實上,遞歸只能在少數情況下使用。例如:當你可以證明分而治之的算法減少你想要執行的任務的複雜性時。 在你的情況下,它根本沒有,所以避免它。你只需填滿 - 也許溢出 - 你的call stack沒有必要。正如別人指出的那樣,你的問題可以用經典循環來解決。

你可以解決這個問題是這樣的:

#include <iostream> 
#include <iomanip> 
#include <cmath> 

int main(void) { 

    double x0 = 0.0; 
    double x1 = 0.0; 
    double eps = 0.0001; 
    double s = 1.0; 
    int i = 0; 
    int maxiter = 100000; 

    do { 
     // Save Previous Term in order to compare with the next: 
     x0 = x1; 
     // Compute Next Term: 
     x1 += s*4.0/(2*static_cast<double>(i)+1); 
     // Change Sign: 
     s *= -1.0; 
     // Increase Counter: 
     i++; 
     // Log: 
     std::cout << std::setw(6) << i << std::fixed << "\t" 
       << x1 << "\t" << std::setw(10) << (x1-x0) << std::endl; 
    // Loop until convergence criterion is met or max iteration is reached: 
    } while((std::abs(x1-x0)>eps)&&(i<maxiter)); 

    return 0; 
} 

如果你不知道它會跑了多少步收斂你需要一個loop而不是for聲明。在你的情況下,loop是沒有必要的,因爲你可以寫下兩個連續項之間的差異,並根據你的epsilon標準確定它需要足夠小的步數。

無論如何,如果你使用一個循環,你必須確保:

  • 循環將永遠退出在某些點(避免無限循環);
  • 退出時,結果是正確的。

這就是爲什麼我在循環條件中使用兩個條件的原因。第二個是沒有必要的,因爲我可以顯示兩個連續項之間的距離隨着i的增長而消失到0。但是我可能希望循環在達到迭代閾值之前停止。