Является ли данный код рекурсивным?

549
03 февраля 2017, 05:23

Есть задание

Найти методом деления отрезка пополам минимум функции f(x) = 7sin(2x) на отрезке [2, 6] с заданной точностью ε (например, 0.01).
Разумеется, его нужно написать

#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;

const double eps = 0.01;
double a, b, t, x, y, t1, s;
double func(double a, double b)
{
    s = (a + b) / 2;
    y = (7 * sin(2)*s);
    return y;
}
int main()
{
    a = 2;
    b = 6;
    while (abs(b - a) < eps);
    {
        t = (a + b) / 2.0;
        y = 7 * sin(2)*(t - eps);
        x = 7 * sin(2)*(t + eps);
        if (y <= x)
        {
            a = t;
            t1 = func(a, b);
        }
        else
        {
            b = t;
            t1 = func(a, b);
        }
    }
    cout << "Otvet: " << t1;
    return 0;
}

Проблема в том, что преподаватель говорит, что задача решена не рекурсивно. Я утверждаю что решение рекурсивно, так как функция double func принимает значение из функции int main. Прав ли я?

Answer 1

Верно будет так (примерны код):

rec(double a, double b){
      (здесь все ваши действия с синусами)
      if (abs(b - a) < eps)  // проверяем новые значения - надо еще раз пересчитать?
            rec(a, b) // вызываем саму себя с новыми значениями
      else return ... // иначе - возвращаем ответ
  }

И в мейне вызываем эту функцию,не забыв передать в нее начальные a и b

Answer 2

Нет, это решение не является рекурсивным. Рекурсия предполагает вызов функции из себя (прямо или косвенно), а в приведённом решении ничего подобного нет.

Более того, приведённое решение визуально кажется мне неверным. Функция не является монотонной, поэтому всякие шаманства со знаками применять, скорее всего, не следует.

На мой взгляд, правильным будет проверять весь отрезок полностью (в условии сказано "методом деления отрезка пополам", но не сказано, что это должен быть бинпоиск, отсекающий половину отрезка).

http://ideone.com/fyRCVW

#include <iostream>
#include <cmath>
using namespace std;
const double EPS = .01;
double f(double x)
{
    return 7 * sin(2*x);
}
double solve(double l, double r)
{
    double m = l / 2 + r / 2;
    if (r-l < EPS)
        return m;
    double x1 = solve(l, m), x2 = solve(m, r);
    return f(x1) < f(x2) ? x1 : x2;
}
int main()
{
    cout << solve(2, 6);
    return 0;
}

Ответ: 2.35547.

Answer 3

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

Вот готовое решение:

    // Найти методом деления отрезка пополам минимум функции f(x) = 7sin(2x) на отрезке [2, 6] с заданной точностью ε (например, 0.01).
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    using namespace std;
    const double eps = 0.01;
    double a, b, t, x, y, t1, s;
    double func(double a, double b, double e)
    {
        s = (a + b) / 2 ;
        t1 = 7 * sin(2*s + e) ;
        return t1;
    }
    void JustDoIt(double &a,double &b)
    {
                t = (a + b) / 2.0;
                y = func(a, b,   - eps);
                x = func(a, b,  eps);
                if (y >= x)    a = t;
                else   b = t;
                // чек-блок 
                     cout << "t= " << t <<"\n";
                     cout << "a= " << a <<" b=" << b <<"\n";
                     cout << "x= " << x <<" y=" << y <<"\n";
                     cout << "fabs(b - a)= " <<  fabs(b - a) <<"\n";
                // 
               if ( fabs(b - a) < eps) return;
                JustDoIt( a, b);
    }
    int main()
    {
       a = 2;
       b = 6;
       JustDoIt( a, b);
       cout << "Otvet: " << func(a, b,0)<<"\n";
        return 0;
    }

Вывод:

a= 4 b=6
x= 6.91498 y=6.93535
fabs(b - a)= 2
a= 5 b=6
x= -3.86669 y=-3.74922
fabs(b - a)= 1
a= 5 b=5.5
x= -6.99927 y=-6.99989
fabs(b - a)= 0.5
a= 5.25 b=5.5
x= -6.19085 y=-6.12428
fabs(b - a)= 0.25
a= 5.375 b=5.5
x= -6.80666 y=-6.77263
fabs(b - a)= 0.125
a= 5.4375 b=5.5
x= -6.95725 y=-6.94041
fabs(b - a)= 0.0625
a= 5.46875 b=5.5
x= -6.99191 y=-6.98379
fabs(b - a)= 0.03125
a= 5.48438 b=5.5
x= -6.99901 y=-6.99525
fabs(b - a)= 0.015625
a= 5.49219 b=5.5
x= -6.99999 y=-6.99843
fabs(b - a)= 0.0078125
Otvet: -6.99996

попутно выявились ошибки в вашем коде: while не выполняется из-за ";" , а блок затем проходит только один раз и вместо abs() нужно использовать fabs().

Answer 4
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;

const double eps = 0.01;
double a, b, t, x, y, t1, s;
double func(double a, double b)
{
 s = (a + b) / 2;
 t1 = (7 * sin(2)*s);
 return t1;
}
double rec(){
 while (abs(b - a) < eps);
 {
    t = (a + b) / 2.0;
    y = 7 * sin(2)*(t - eps);
    x = 7 * sin(2)*(t + eps);
    if (y <= x)
    {
        a = t;
        t1 = func(a, b);
    }
    else
    {
        b = t;
        t1 = func(a, b);
    }
 }
}
 int main()
 {
 a = 2;
 b = 6;
 rec();
 cout << "Otvet: " << t1;
 return 0;
 }
READ ALSO
Stringgrid, откат предыдущего действия (С++ Builder 6.0) [требует правки]

Stringgrid, откат предыдущего действия (С++ Builder 6.0) [требует правки]

Есть элемент stringgrid в который я вношу данные, могу добавлять, изменять через отдельные формы и результат сохраняется в stringgridНеобходимо сделать...

351
Vulkan и GLFW в полноэкранном режиме - мигание при выходе или переключении на рабочий стол

Vulkan и GLFW в полноэкранном режиме - мигание при выходе или переключении на рабочий стол

Использую Вулкан и GLFW для работы в полноэкранном режимеЕсть проблема - при выходе из приложения или просто переключении на рабочий стол возникает...

400
Как подключить библиотеку SFML к CLion проекту? [требует правки]

Как подключить библиотеку SFML к CLion проекту? [требует правки]

Как подключить библиотеку SFML к CLion проекту?

551
vector vs valarray

vector vs valarray

Зачем нужен std::vector<>, если есть потенциально более быстрый std::valarray<>?

374