Как исправить код «PI recursive function» для работы со всеми значениями n? - PullRequest
1 голос
/ 07 апреля 2019

Я работаю над кодом, который вычисляет PI с n терминами. Однако мой код корректно работает только с некоторыми значениями n.

Эта часть кода четных чисел не работает, и когда я переключаю отрицательный знак, нечетные числа не работают.

double PI(int n, double y=2){

    double sum = 0;
    if (n==0){
        return 3;
    }else if (n % 2 != 0){
        sum =  (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;

    }else{
        sum=  -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2)  ;
    }
    return sum;
} 

  int main(int argc, const char * argv[]) {
    double n = PI (2,2);
    cout << n << endl;
   }

Для n = 2 я ожидал результата 3,1333, но получил значение 2,86667 Это формула для вычисления PI, у - знаменатель, а n - число слагаемых. enter image description here

Ответы [ 2 ]

4 голосов
/ 07 апреля 2019

Во-первых, я предполагаю, что полный исполняемый регистр вашего кода выглядит как

#include <iostream>
using namespace std;

double PI(int n, double y=2){

    double sum = 0;
    if (n==0){
        return 3;
    }else if (n % 2 != 0){
        sum =  (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;

    }else{
        sum=  -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2)  ;
    }
    return sum;
}

int main(int argc, const char * argv[]) {
  double n = PI (2,2);
  cout << n << endl;
}

Я полагаю, что вы пытаетесь вычислить число Пи по формуле

(pi - 3)/4 = \sum_{k = 1}^{\infty} (-1)^{k+1} / ((2k(2k+1)(2k+2)),

(гдездесь и в других местах я использую код LaTeX для представления математических вещей).Это хорошая формула, которая сходится довольно быстро, несмотря на свою простоту.Если бы вы использовали первые два слагаемых суммы, вы бы обнаружили, что

(pi - 3)/4 \approx 1/(2*3*4) - 1/(4*5*6)  ==>  pi \approx 3.13333,

, который вы указали в своем вопросе.

Чтобы увидеть, что не так, вы могли бы проследить черезВаш первый вызов функции с PI (2, 2).Это дает три условия.

  1. n = 2: 2% 2 == 0, поэтому первый член - -4/(2*3*4) + PI(1, 4).Это неправильный знак.
  2. n = 1: 1% 2 == 1, поэтому второе слагаемое - 4/(4*5*6), что также является неправильным знаком.
  3. n = 0: n== 0, поэтому третий член равен 3, что является правильным знаком.

Итак, вы вычислили

3 - 4/(2*3*4) + 4/(4*5*6)

, и мы видим, что существует много ошибок знака.

Основная причина в том, что вы определяете знак на основе n, но если вы изучите формулу, знак зависит от y.Или, в частности, это зависит от того, является ли y/2 нечетным или четным (в вашей формулировке, где вы, очевидно, собираетесь предоставить только y значения для вашей суммы).

Вам следует изменить yи n соответственно.Или вы можете признать, что нет причин разъединять их и использовать что-то вроде следующего кода.В этом коде n представляет количество используемых терминов, и мы вычисляем y соответственно.

#include <iostream>
using namespace std;

double updatedPI(int n)
{
  int y = 2*n;
  if (n == 0) { return 3; }
  else if (n % 2 == 1)
  {
    return 4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
  }
  else
  {
    return -4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
  }
}

int main() {
  double n = updatedPI(3);
  cout << n << endl;
}
1 голос
/ 07 апреля 2019

Единственная проблема с вашим кодом состоит в том, что y рассчитывается неправильно. Он должен быть равен 2 * n. Простое изменение кода таким образом дает правильные результаты:

Живая демоверсия: https://wandbox.org/permlink/3pZNYZYbtHm7k1ND

То есть, избавьтесь от параметра функции y и установите int y = 2 * n; в вашей функции.

...