Я работаю над кодом, который вычисляет 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 — количество слагаемых.
Не могли бы вы показать математическую формулу, реализованную в вашем коде? Что такое n
и y
? Откуда вы взяли эти ожидаемые значения?
Кстати, каждый раз, когда вы используете рекурсия, вы используете больше памяти стека (включая обычные данные вызова функций и локальные переменные). Недостаточно места в стеке для Н, когда количество повторений Н становится большим. Предпочитайте итеративный подход или используйте стек.
Во-первых, я предполагаю, что полный работоспособный вариант вашего кода выглядит так:
#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). Это дает три термина.
-4/(2*3*4) + PI(1, 4)
. Это неправильный знак.4/(4*5*6)
, что также является неправильным знаком.Итак, вы вычислили
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
.
@DanielLangr Кажется, ты говоришь то же самое, что и я. Проблема со знаком в его текущем коде связана с тем, что отношения между его y
и n
неверны. Я описываю фактическое вычисление, чтобы показать, что его неправильное отношение вызывает проблему со знаком. Или вы намекаете на какое-то другое несоответствие?
Вы правы, извините, я неправильно истолковал ваш ответ, мой плохой. К сожалению, я не могу проголосовать за него, если он не отредактирован :(.
LaTeX здесь не работает, поэтому вам, вероятно, следует писать простым текстом, поскольку большинство людей, таких как я, не могут легко читать LaTeX.
Единственная проблема с вашим кодом в том, что y
вычисляется неправильно. Он должен быть равен 2 * n
. Простое изменение кода таким образом дает правильные результаты:
Живая демонстрация: https://wandbox.org/permlink/3pZNYZYbtHm7k1ND
То есть избавьтесь от параметра функции y
и установите int y = 2 * n;
в своей функции.
Я рекомендую добавить заголовки и т. д. коду нужно, чтобы потенциальные ответчики могли поместить ваш пример в текстовый файл, скомпилировать и запустить. Я также рекомендую добавить то, что вы получили вместо ожидаемого. Этот дополнительный бит информации часто содержит информацию, которая мгновенно предлагает потенциальные ответы.