2013-12-07 3 views
-3

Я попытался создать программу на C, в которой проблема: x = 4/1 - 4/3 + 4/5 - 4/7 + 4/9 ....Код рекурсии серии 4/1 - 4/3 + 4/5

условие остановки, когда значение «х» вычисляются в предыдущем взаимодействии менее 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

'calc' всегда 4 при достижении' if (calc == 0.0001) ', поэтому он никогда не вызовет возврата – 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

Я предполагаю это то, что сказал Google. – remus

2

Я не думаю, что рекурсия необходима. Это легко решить с помощью итерации. Я вижу следующий рисунок. Знаменатель составляет 1,3,5,7 нечетные числа. Это i% 2. Знак дроби чередуется между + и -. Используйте модуль 2 итерации, чтобы умножить текущую долю на -1 или нет. Тогда + = к текущей сумме.

+0

спасибо за помощь, потому что он уже сделал это интерактивно, эта проблема начала заставлять меня делать рекурсивные, и я новый студент в области программирования –

0
  1. В этом фрагменте кода:

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

    е всегда 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 

И на каждом шагу, это выглядит, как вы хотите добавить, что дельту общая:

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.

Во всяком случае, если вы используете цикл, вы должны убедиться, что:

  • Loop будет когда-нибудь выйти на какой-то момент (во избежание бесконечного цикла);
  • При выходе из строя результат верный.

Именно по этой причине я использую два критерия в моем состоянии цикла. Второе не нужно, так как я могу показать, что расстояние между двумя последовательными членами обращается в нуль до 0, так как i растет. Но я, возможно, захочу, чтобы цикл остановился, прежде чем я достиг некоторого порога итерации.

Смежные вопросы