Turbo_pudge_2007

Пользователь

Регистрация: 08.11.2019

Сообщения: 680

Рейтинг: 302

Нарушения: 1000

Turbo_pudge_2007

Регистрация: 08.11.2019

Сообщения: 680

Рейтинг: 302

Нарушения: 1000

Как писали выше твоя прога вообще не работает, там зацикливание, я точно хз что искать предел и тем более заниматься отладкой лень, у меня мобильный компилятор выводит числа и пишет trap


#include "iostream"
#include "cmath"

double f(double x, double a){
double xn = (a * x)/ 5.0 + 4/(5.0 * pow(x, 4.0));
if((a * abs(xn - x) * 5.0)/4.0 < 1.0/1000000.0){
std::cout << x << std::endl;
std::cout << a - pow(x, 5.0) << std::endl;
}
else{
f(xn, a);
}
}

int main()
{
double a;
std::cin >> a;
double x0;
if(a <= 1){
x0 = fmin(2.0 * a, 0.95);
}
else{
if(a <= 25.0){
x0 = a / 5.0;
}
else{
x0 = a / 25.0;
}
}
f(x0, a);
}

kekmachine

Пользователь

Регистрация: 14.08.2018

Сообщения: 1610

Рейтинг: 614

kekmachine

Регистрация: 14.08.2018

Сообщения: 1610

Рейтинг: 614

ScienceT сказал(а):


В задании точно нет какой-либо опечатки? Ибо "нормально" считает только при 0 < a <= 5 (причём при а = 5 и e=1E-06 за 20 млн. итераций нет остановки), а в остальных случаях улетает в overflow (слишком большие числа).

Нажмите, чтобы раскрыть...

Ща на шарпе быстро накидал условия задачи, все как у тебя(правда для 1-3 еще быстрее улетает в эксепшн), мне кажется проблема в левой части сравнения с 10^-6, мб мы ее неправильно интерпретировалиISSOU.png

Орион Туман

Пользователь

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

Орион Туман

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

CloneBoiii~ сказал(а):

Гайзевичи, у меня траблы с математикой, помогите с этой прогой, прошумолюBlessRNG.png

Спойлер: "Задание"

Нажмите, чтобы раскрыть...

В этой реализации нет защиты от переполнения типа double, поэтому используй малые цифры для достоверного результата.

Спойлер: "Листинг"

#include <iostream>
#include <cmath>
#include <iomanip>
#include <locale.h>

 

using namespace std;

 

double a; //по условию a>0
double x0;
bool rez = 0;
double f, m;
int n;

 

void correct(double x)
{
   if (x <= 0)
   {
      cout << "\nЧисло не должно противоречить условию!\n";
      cout << "Введите другое число: ";
      cin >> a;
      correct(a);
   }
return;
}

 

//x0 для создания последовательности
double x_0(double a)
{
   if (a <= 1)
      return (2.0 * a < 0.95) ? 2.0 * a : 0.95;
   if (a <= 25)
      return a / 5.0;

return a / 25.0;
}

 

//функция рекурсивного вычисления
double xPosled(int n)
{
   double x;
   if (n == 1)
      x = (a * x0) / 5.0 + 4.0 / (5.0 * x0 * x0 * x0 * x0);
   else
   {
      x = xPosled(n - 1);
      x = (a * x) / 5.0 + 4.0 / (5.0 * x * x * x * x);
   }
return x;
}

 

int main()
{
   setlocale(LC_ALL, "");
   cout << "Введите действительное число а>0: ";
   cin >> a;
   correct(a);
   x0 = x_0(a); //определение x0
   cout << "\nx(0) = " << x0;
   cout << "\n\nВведите верхнюю границу последовательности n=1,2,3...";
   cin >> n;
   cout << "\nИдёт рассчет...";

//рекурсия в цикле (вызовы ограничены числом n)
for (int i = 1; i <= n; ++i)
   if (5.0 * a * abs(xPosled(i + 1) - xPosled(i)) / 4.0 < 1.0 / 1000000.0)
      {
      rez = 1;
      m = xPosled(i);
      f = i;
      break;
      }

 

if (!rez)
   cout << "\rВ диапазоне n = 1..."<< n << " нет ни одного числа, удовлетворяющего условию.\n\n";
else
   cout << "\rДля x(" << f << ") = " << m << " разность равна " << a - m * m * m * m * m << "\n\n";

 

system("PAUSE");
return 0;
}

Дополнительно проверил в MathCAD для точности при a=0.0000008 результат работы достоверен:

Спойлер: "a = 8 * 10^(-7)"

Введите действительное число а>0: 0.0000008

x(0) = 1.6e-06

Введите верхнюю границу последовательности n=1,2,3...1000

Для x(78) = 1.05903 разность равна -1.33211

Для продолжения нажмите любую клавишу . . .

При a=4 результат работы достоверен:

Спойлер: "a = 4"

Введите действительное число а>0: 4

x(0) = 0.8

Введите верхнюю границу последовательности n=1,2,3...100

Для x(8) = 1.31951 разность равна -5.10845e-11

Для продолжения нажмите любую клавишу . . .

P.S.: Для других значений может возникнуть переполнение типа double... поэтому нужно проверять ответы отдельно или дописывать хитрость защиты от переполнения. Не вводи верхнюю границу цикла больше 1000, иначе может зависнуть, либо аварийно завершится консоль.


Но по условию - написать программу, ищущую ответ с помощью рекурсии на С++, выполнено как следует. Для указанных a - ответы достоверны.

CloneBoiii~

Пользователь

Регистрация: 03.11.2016

Сообщения: 630

Рейтинг: 374

CloneBoiii~

Регистрация: 03.11.2016

Сообщения: 630

Рейтинг: 374

img
Орион Туман сказал(а):

В этой реализации нет защиты от переполнения типа double, поэтому используй малые цифры для достоверного результата.

Спойлер: "Листинг"

#include <iostream>
#include <cmath>
#include <iomanip>
#include <locale.h>

 

using namespace std;

 

double a; //по условию a>0
double x0;
bool rez = 0;
double f, m;
int n;

 

void correct(double x)
{
   if (x <= 0)
   {
      cout << "\nЧисло не должно противоречить условию!\n";
      cout << "Введите другое число: ";
      cin >> a;
      correct(a);
   }
return;
}

 

//x0 для создания последовательности
double x_0(double a)
{
   if (a <= 1)
      return (2.0 * a < 0.95) ? 2.0 * a : 0.95;
   if (a <= 25)
      return a / 5.0;

return a / 25.0;
}

 

//функция рекурсивного вычисления
double xPosled(int n)
{
   double x;
   if (n == 1)
      x = (a * x0) / 5.0 + 4.0 / (5.0 * x0 * x0 * x0 * x0);
   else
   {
      x = xPosled(n - 1);
      x = (a * x) / 5.0 + 4.0 / (5.0 * x * x * x * x);
   }
return x;
}

 

int main()
{
   setlocale(LC_ALL, "");
   cout << "Введите действительное число а>0: ";
   cin >> a;
   correct(a);
   x0 = x_0(a); //определение x0
   cout << "\nx(0) = " << x0;
   cout << "\n\nВведите верхнюю границу последовательности n=1,2,3...";
   cin >> n;
   cout << "\nИдёт рассчет...";

//рекурсия в цикле (вызовы ограничены числом n)
for (int i = 1; i <= n; ++i)
   if (5.0 * a * abs(xPosled(i + 1) - xPosled(i)) / 4.0 < 1.0 / 1000000.0)
      {
      rez = 1;
      m = xPosled(i);
      f = i;
      break;
      }

 

if (!rez)
   cout << "\rВ диапазоне n = 1..."<< n << " нет ни одного числа, удовлетворяющего условию.\n\n";
else
   cout << "\rДля x(" << f << ") = " << m << " разность равна " << a - m * m * m * m * m << "\n\n";

 

system("PAUSE");
return 0;
}

Дополнительно проверил в MathCAD для точности при a=0.0000008 результат работы достоверен:

Спойлер: "a = 8 * 10^(-7)"

Введите действительное число а>0: 0.0000008

x(0) = 1.6e-06

Введите верхнюю границу последовательности n=1,2,3...1000

Для x(78) = 1.05903 разность равна -1.33211

Для продолжения нажмите любую клавишу . . .

При a=4 результат работы достоверен:

Спойлер: "a = 4"

Введите действительное число а>0: 4

x(0) = 0.8

Введите верхнюю границу последовательности n=1,2,3...100

Для x(8) = 1.31951 разность равна -5.10845e-11

Для продолжения нажмите любую клавишу . . .

P.S.: Для других значений может возникнуть переполнение типа double... поэтому нужно проверять ответы отдельно или дописывать хитрость защиты от переполнения. Не вводи верхнюю границу цикла больше 1000, иначе может зависнуть, либо аварийно завершится консоль.


Но по условию - написать программу, ищущую ответ с помощью рекурсии на С++, выполнено как следует. Для указанных a - ответы достоверны.

Нажмите, чтобы раскрыть...

омг просто, ты лучший, без сарказма. огромное спасибоAnimeHugs.png

Орион Туман

Пользователь

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

Орион Туман

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

"CloneBoiii"

Привет, слушай, а можешь как-то сделать без глобальных переменных? И суть задания оказалась в том, чтоб рекурсией искалось первое подходящее значение по условию, его и нужно вывести как ответ


Спойлер: "Новый листинг"

#include <iostream>
#include <cmath>
#include <iomanip>
#include <locale.h>

 

double correctir(double);

 

double vvod()
{
   std::cout << "Введите действительное число а>0: ";
   double a;
   std::cin >> a;
   a = correctir(a);
   return a;
}

 

double correctir(double a)
{
   if (a <= 0)
   {
      std::cout << "\rЧисло не должно противоречить условию!, - ";
      a = vvod();
   }
   return a;
}

 

double x_0(double a)
{
   if (a <= 1)
      return (2.0 * a < 0.95) ? 2.0 * a : 0.95;
   if (a <= 25)
      return a / 5.0;

 

   return a / 25.0;
}

 

double reqursia(size_t n, double a, double x0)
{

   double x;
   if (n == 1)
      x = (a * x0) / 5.0 + 4.0 / (5.0 * x0 * x0 * x0 * x0);
   else
   {
      x = reqursia(n - 1, a, x0);
      x = (a * x) / 5.0 + 4.0 / (5.0 * x * x * x * x);
   }
   return x;
}

 

void rasschet(double a, double x0)
{
   std::cout << "\rИдёт поиск первого подходящего значения x (по условию)...";
   for (size_t i = 1; i <= 4294967294; i++)
   {
      if (i == 4294967294)
      {
         std::cout << "\rПереполнение 32 битного числа! Расчёт остановлен, 'x' не найден.";
         break;
      }
      double b = reqursia(i + 1, a, x0);
      double m = reqursia(i, a, x0);
      if (5.0 * a * abs(b - m) / 4.0 < 1.0 / 1000000.0)
      {
         std::cout << "\nx_" << i << " = " << m << "\n";
         break;
      }
   }
}

 

void mainCircle()
{
   double a = vvod();
   double x0 = x_0(a);
   rasschet(a, x0);
   std::cout << "\n";
   mainCircle();
}

 

int main()
{
   setlocale(LC_ALL, "");
   mainCircle();

   return 0;
}

Спойлер: "Результаты работы с некоторыми 'a'"

Введите действительное число а>0: -1
Число не должно противоречить условию!, - Введите действительное число а>0: 0.0000008
Идёт поиск первого подходящего значения x (по условию)...
x_78 = 1.05903

 

Введите действительное число а>0: 0.0000009
Идёт поиск первого подходящего значения x (по условию)...
x_40 = 0.911434

 

Введите действительное число а>0: 4.5
Идёт поиск первого подходящего значения x (по условию)...
x_24 = 1.51572

 

Введите действительное число а>0: 4
Идёт поиск первого подходящего значения x (по условию)...
x_8 = 1.31951


P.S.: Для указанных 'a' - ответы достоверны. Другие 'x' могут быть ошибочными из-за переполнения типа "double", поэтому нужно проверять отдельно, так как защиты от переполнения нет - сверяй другие ответы самостоятельно, например с помощью MathCAD.... Ошибка в работе вызовет аварийное закрытие консоли. Явного выхода из программы нет - цикл запроса 'а' бесконечен, поэтому, чтобы завершить работу консоли, используй символ X - в правом верхнем углу окна.

ForeverYang

Пользователь

Регистрация: 28.03.2019

Сообщения: 12411

Рейтинг: 3107

ForeverYang

Регистрация: 28.03.2019

Сообщения: 12411

Рейтинг: 3107

If тебе в помощь, а так это изи

Орион Туман

Пользователь

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

Орион Туман

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

"CloneBoiii"

в общем, поговорил с преподом, показал ей значения при которых работает. сказала, что если ограничить поиск до 1000, то стек не должен переполняться и прога должна работать. хз, сможешь потестить? может даже меньше 1000, если потребуется


Твоя бабка начала "умничать" и на нервы действовать.


Замени тело функции void rasschet(double a, double x0) на следующее:

Спойлер: "Корректировка одной функции из предыдущего листинга"

void rasschet(double a, double x0)
{
   std::cout << "\rПоиск первого значения x (по условию)...";
   for (size_t i = 1; i <= 5000U; i++)
   {
      if (i == 1001 || i == 2001 || i == 3001)
      {
         std::cout << "\rВ диапазоне от 1 до " << i - 1 << ", x = НЕ найден! Продолжить? (1/0 = да/нет): ";
         int r;
         std::cin >> r;
         if (r != 1)
         {
            std::cout << "Рекурсивный поиск остановлен.\n";
            break;
         }
         std::cout << "\rПродолжается поиск...";
      }
      else if (i == 4001)
      {
         std::cout << "\rВ диапазоне от 1 до " << i - 1 << ", x = НЕ найден! Продолжение вызовет переполнение стека\n";
         std::cout << "Рекурсивный поиск остановлен.\n";
         break;
      }
      double b = reqursia(i + 1, a, x0);
      double m = reqursia(i, a, x0);
      if (5.0 * a * abs(b - m) / 4.0 < 0.000001)
      {
         std::cout << "\nx_" << i << " = " << m << "\n";
         break;
      }
   }

}


P.S.: Вводи любое значение a= от 3,01 до 4,99 с шагом 0,01. Переменная типа Double, в данном диапазоне не переполняется, поэтому "x" находит корректно, даже если оно больше 1000.


При а= от бесконечно малого числа до 1 функция прыгает, как пилообразный сигнал и там, случайно попадать в значения не имеет смысла.

При а= от ~1 до ~3, "х" не существует.

При а= от 5 до ∞, либо не существует "х", либо он настолько большой, что возникает переполнение. Так что значения >5 вводить так же не имеет смысла.


Несколько любых чисел от 3,01 до 4,99 для примера работы:

Введите действительное число а>0: 3.01
В диапазоне от 1 до 1000, x = НЕ найден! Продолжить? (1/0 = да/нет): 1
Продолжается поиск...
x_1254 = 1.14985


Введите действительное число а>0: 3.3
Поиск первого значения x (по условию)...
x_42 = 1.18665


Введите действительное число а>0: 3.98
Поиск первого значения x (по условию)...
x_8 = 1.31429


Введите действительное число а>0: 4.1
Поиск первого значения x (по условию)...
x_11 = 1.34761


Введите действительное число а>0: 4.55
Поиск первого значения x (по условию)...
x_26 = 1.548


Введите действительное число а>0: 4.87
Поиск первого значения x (по условию)...
x_84 = 1.98437


Введите действительное число а>0: 4.99
В диапазоне от 1 до 1000, x = НЕ найден! Продолжить? (1/0 = да/нет): 1
Продолжается поиск...
x_1053 = 3.31444

white_dog

Пользователь

Регистрация: 29.08.2019

Сообщения: 1697

Рейтинг: 38

Нарушения: 1000

white_dog

Регистрация: 29.08.2019

Сообщения: 1697

Рейтинг: 38

Нарушения: 1000

Орион Туман сказал(а):

"CloneBoiii"

в общем, поговорил с преподом, показал ей значения при которых работает. сказала, что если ограничить поиск до 1000, то стек не должен переполняться и прога должна работать. хз, сможешь потестить? может даже меньше 1000, если потребуется


Твоя бабка начала "умничать" и на нервы действовать.


Замени тело функции void rasschet(double a, double x0) на следующее:

Спойлер: "Корректировка одной функции из предыдущего листинга"

void rasschet(double a, double x0)
{
   std::cout << "\rПоиск первого значения x (по условию)...";
   for (size_t i = 1; i <= 5000U; i++)
   {
      if (i == 1001 || i == 2001 || i == 3001)
      {
         std::cout << "\rВ диапазоне от 1 до " << i - 1 << ", x = НЕ найден! Продолжить? (1/0 = да/нет): ";
         int r;
         std::cin >> r;
         if (r != 1)
         {
            std::cout << "Рекурсивный поиск остановлен.\n";
            break;
         }
         std::cout << "\rПродолжается поиск...";
      }
      else if (i == 4001)
      {
         std::cout << "\rВ диапазоне от 1 до " << i - 1 << ", x = НЕ найден! Продолжение вызовет переполнение стека\n";
         std::cout << "Рекурсивный поиск остановлен.\n";
         break;
      }
      double b = reqursia(i + 1, a, x0);
      double m = reqursia(i, a, x0);
      if (5.0 * a * abs(b - m) / 4.0 < 0.000001)
      {
         std::cout << "\nx_" << i << " = " << m << "\n";
         break;
      }
   }

}


P.S.: Вводи любое значение a= от 3,01 до 4,99 с шагом 0,01. Переменная типа Double, в данном диапазоне не переполняется, поэтому "x" находит корректно, даже если оно больше 1000.


При а= от бесконечно малого числа до 1 функция прыгает, как пилообразный сигнал и там, случайно попадать в значения не имеет смысла.

При а= от ~1 до ~3, "х" не существует.

При а= от 5 до ∞, либо не существует "х", либо он настолько большой, что возникает переполнение. Так что значения >5 вводить так же не имеет смысла.


Несколько любых чисел от 3,01 до 4,99 для примера работы:

Введите действительное число а>0: 3.01
В диапазоне от 1 до 1000, x = НЕ найден! Продолжить? (1/0 = да/нет): 1
Продолжается поиск...
x_1254 = 1.14985


Введите действительное число а>0: 3.3
Поиск первого значения x (по условию)...
x_42 = 1.18665


Введите действительное число а>0: 3.98
Поиск первого значения x (по условию)...
x_8 = 1.31429


Введите действительное число а>0: 4.1
Поиск первого значения x (по условию)...
x_11 = 1.34761


Введите действительное число а>0: 4.55
Поиск первого значения x (по условию)...
x_26 = 1.548


Введите действительное число а>0: 4.87
Поиск первого значения x (по условию)...
x_84 = 1.98437


Введите действительное число а>0: 4.99
В диапазоне от 1 до 1000, x = НЕ найден! Продолжить? (1/0 = да/нет): 1
Продолжается поиск...
x_1053 = 3.31444

Нажмите, чтобы раскрыть...


пол месяца решать задачку, сильно сильно

Орион Туман

Пользователь

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

Орион Туман

Регистрация: 22.03.2015

Сообщения: 778

Рейтинг: 591

white_dog сказал(а):


пол месяца решать задачку, сильно сильно

Нажмите, чтобы раскрыть...

А чем ты? Задача была решена за несколько часов еще 18-го и работала, остальное - изменения по прихоти преподавателя.

white_dog

Пользователь

Регистрация: 29.08.2019

Сообщения: 1697

Рейтинг: 38

Нарушения: 1000

white_dog

Регистрация: 29.08.2019

Сообщения: 1697

Рейтинг: 38

Нарушения: 1000

Орион Туман сказал(а):

А чем ты? Задача была решена за несколько часов еще 18-го и работала, остальное - изменения по прихоти преподавателя.

Нажмите, чтобы раскрыть...

Так ты ж не тс, я чет запутался