Как исправить код «Рекурсивная функция PI» для работы со всеми значениями n?

Я работаю над кодом, который вычисляет 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, y — знаменатель, а n — количество слагаемых. Как исправить код «Рекурсивная функция PI» для работы со всеми значениями n?

Я рекомендую добавить заголовки и т. д. коду нужно, чтобы потенциальные ответчики могли поместить ваш пример в текстовый файл, скомпилировать и запустить. Я также рекомендую добавить то, что вы получили вместо ожидаемого. Этот дополнительный бит информации часто содержит информацию, которая мгновенно предлагает потенциальные ответы.

user4581301 07.04.2019 17:52

Не могли бы вы показать математическую формулу, реализованную в вашем коде? Что такое n и y? Откуда вы взяли эти ожидаемые значения?

Daniel Langr 07.04.2019 18:14

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

Thomas Matthews 07.04.2019 19:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

#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;
}

Я не думаю, что ответ правильный. С песнями проблем нет. Единственная проблема с кодом OP заключается в том, что y неверно, так как он не равен 2*n.

Daniel Langr 07.04.2019 19:25

@DanielLangr Кажется, ты говоришь то же самое, что и я. Проблема со знаком в его текущем коде связана с тем, что отношения между его y и n неверны. Я описываю фактическое вычисление, чтобы показать, что его неправильное отношение вызывает проблему со знаком. Или вы намекаете на какое-то другое несоответствие?

davidlowryduda 07.04.2019 19:34

Вы правы, извините, я неправильно истолковал ваш ответ, мой плохой. К сожалению, я не могу проголосовать за него, если он не отредактирован :(.

Daniel Langr 07.04.2019 19:36

LaTeX здесь не работает, поэтому вам, вероятно, следует писать простым текстом, поскольку большинство людей, таких как я, не могут легко читать LaTeX.

eesiraed 07.04.2019 23:20

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

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

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

Другие вопросы по теме