C++

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 16 сен 2017, 17:08

Вопрос не просто детский а младенческий. Работает ли эта программа (a=0,b=1,eps=0.001)и какой дает результат?

Код: Выбрать все

#include "stdafx.h"
#include <iostream>

using namespace std;
//Функция для уравнения:
double F(double x) {
   return  2 - 20 * x + 9 * pow(x, 2) - pow(x, 3);
}
//Функция поиска корня:
int main()
{
   //Интервал, погрешность и корень:
   double a, b, eps, x;
   cin >> a;
   cin >> b;
   //Проверка корректности интервала:
   if (F(a)*F(b) > 0) {
      cout << "Wrong interval!\n";
      return 0;
   }
   cout << "error: ";
   cin >> eps;
   int k = 0;
   //Поиск решения:
   do {
      x= a-(F(a)*(b-a)) / (F(b) - F(a));
      if ((F(a)*F(x)) > 0)
         a = x;
      else
         b = x;
      k++;
   } while (fabs(F(b) - F(a)) > eps II fabs(a-b)>2*eps);
   cout << "x = " << x << endl;
   cout << "f(x)=" << F(x) << endl;
   cout << "k=" << k<<endl;
   system("pause");
   return 0;
}
Заранее спасибо за потраченное время

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 17:59

Так на первый взгляд у Вас есть кубический многочлен [math]. Вы задаёте начальный интервал (a,b) и точность "eps".
Проверяете, что в "a" и "b" многочлен имеет значения с разными знаками (и значит в интервале должен быть корень).
И ищете этот корень методом хорд с точностью "eps".
На выходе сам корень (приближенно), значение многочлена в этой точке и количество итераций.

Багов вроде нет на первый взгляд.
Этот многчлен имеет ровно один корень на интервале (0,1). Так что должно сработать.

PS: В условии "while" я бы заменил "or" на "and" для безопасности. А то может войти в вечный цикл в редких случаях. (Для данных параметров не должно.)

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 18:41

zykov писал(а):Source of the post А то может войти в вечный цикл в редких случаях.

Кстати, на самом деле даже не в редких, а в самых обычных (для метода хорд), в том числе и в вашем. Вот для метода деления пополам было бы редко.
Если посмотрите на график своего многочлена в интервале от 0 до 1, то увидите, что он имеет выпуклось вниз. Значит хорды всегда будут выше графика. На каждой итерации Вы будете заменять "b" на новый (всё ближе к корню), а вот "a" так и останется нулём. Так что разность "a-b" не будет приближатся к нулю и второе условие всегда будет верным (а значит всё "или" условие будет верным и цикл никогда не закончится).

PS: Для отладки можно было бы печатать "a" и "b" на каждой итерации, тогда Вы бы сами это быстро заметили.

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 16 сен 2017, 18:46

Спасибо, я знаю. А запустите?
Более точный чем нужно x= 0.1048935 но мне интереснее какой выдаст и конечно сколько было циклов (k)

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 19:18

Если не исправите "or" на "and", то никакой не выдаст.
Зациклится бесконечно.

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 19:24

На самом деле у меня закончился. Но только из-за ошибок округления.

Код: Выбрать все

0
1
error: 0.001
  trace: 1  0  0.166667
  trace: 2  0  0.107946
  trace: 3  0  0.105041
  trace: 4  0  0.104901
  trace: 5  0  0.104894
  trace: 6  0  0.104894
  trace: 7  0  0.104893
  trace: 8  0  0.104893
  trace: 9  0  0.104893
  trace: 10  0  0.104893
  trace: 11  0  0.104893
  trace: 12  0  0.104893
  trace: 13  0.104893  0.104893
x = 0.104893
f(x)=2.01662e-017
k=13


На 13ой итерации всё таки "a" заменил, хотя не должен был в идиале.

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 16 сен 2017, 19:32

zykov писал(а):Если не исправите "or" на "and", то никакой не выдаст.
Зациклится бесконечно.

Спасибо, исправлю. Но мне не на чем это гонять. Уже 10 лет так "программирую" -посылаю кому-то из "клубней" текст, в ответ получаю письмом результат счета. А что, я же им тоже на их вопросы отвечаю.

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 20:26

В смысле? Нет компьютера и на форум через планшет/телефон заходите?

Всё понятно с округлением?
В данном случае цикл случайно закончился из-за ошибки округления. А так вполне мог бы крутится бесконечно.
Идеальное вещественное число "x" всегда будет справа от корня. Но здесь, в результате округления машинного числа с плавующей точкой ('double") оно оказалось слева от корня и заместило "a", в результате чего разность "b-a" оказалась близкой к нулю.
Можно сказать, случайно оказалось. Могло бы так и оставаться справа.

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 16 сен 2017, 20:38

Как помните Кнуров сказал -на столе полно а я голодный) Компа не то что нет а нет хорошего. Дистрибутива нет хорошего. И как Матроскин сказал нам ума не хватает. Вот в 1982 на любом в мире компе был файл C:\basic.exe и каждый знал запусти его и вбивай прогу. На нем бы я эту задачу за 10 минут посчитал. А прогресс видимо катится назад, у скольки профессоров уже время отнял за 10-то лет.

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 21:43

Ну для C++ хороший компьютер и не нужен.

Под linux всегда есть GCC (если нет, то легко поставить). Там эту программу легко собрать (только заменить Микрософтовский "stdafx.h" на другое - здесь достаточно <cmath>).
Под windows я себе поставил mingw (точнее mingw-w64, чтобы 64-битные собирать). Это почти тот же GCC, только собирает виндовс-бинарники, которые под видовс запускаются. Этот пример я так под видовс и проверил. Под linux возможно другой результат был бы (хотя вряд ли).

С языком C/C++ вообще работали или только с Basic?

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 16 сен 2017, 22:31

Как-то работал, у меня жил лето гость с нотбуком, С++ это его хлеб. Он показал мне какой файл запускать и я гонял программы. И если вспомнить одного мужика которому захотелось газировки но не понял военно-морского юмора-это же самому хозяину выгодно чтобы у каждой кнопки был ясно и правдиво указан ее смысл. Как файл-то называется????

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 16 сен 2017, 22:49

В GCC две команды "gcc" и "g++" (вторая лучше для C++). В mingw тоже самое. Это все в терминале надо.
Если Вам Microsoft Visual C++ ставили, то там среду нужно запускать. (Можно в принципе и в терминале, там команда "cl".)

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 16 сен 2017, 23:58

самый простой надо дистрибутив. Установщики, пытающиеся переконфигурировать систему под себя, сработают только если аккуратно написаны и(!) если система исправна, а неисправную систему они просто грохнут, а встать под нее не смогут
На что заменять "или" (||)? на амперсенд ()?

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 17 сен 2017, 00:16


zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 17 сен 2017, 09:30

Чего-то я вчера протупил. Вот это условие "fabs(F(b) - F(a)) > eps II fabs(a-b)>2*eps" вообще не работает для метода хорд (ни с "or", ни с "and") в отличии от метода деления пополам например.
Дело в том, что для метода хорд в обычном случае "a" и "b" не приближаются друг к другу. И соответственно "F(a)" и "F(b)" не приближаются друг к другу.

Тут было бы логично условие "fabs(F(x)) > eps".
Чтобы избежать возможного зацикливания (например если eps близко к машинной точности, а функция не очень хорошая), можно по "and" добавить условие "fabs(x - x1) > eps1". Здесь "x1" - это "x" с предыдущей итерации, "eps1" - это другое эпсилон, которое фиксированно и подбирается исходя из машинной точности.


PS: Вообще метод хорд - не особо хороший метод. Деление пополам гораздо надёжнее и почти так же быстро сходится. А индустриальный стандарт - это метод Ньютона. Он гораздо быстрее сходится, если нужна высокая точность. А для многомерного случаю это по сути единственный метод.

Аватар пользователя
Ian
Сообщений: 708
Зарегистрирован: 18 янв 2016, 19:42

C++

Сообщение Ian » 17 сен 2017, 11:09

zykov писал(а):Тут было бы логично условие "fabs(F(x)) > eps"..

Спасибо, так и сделал. А для функций, производная которых больше 1 на отрезке, это и гарантия точности по х.

zykov
Сообщений: 1059
Зарегистрирован: 06 янв 2016, 17:41

C++

Сообщение zykov » 17 сен 2017, 15:11

Ian писал(а):Source of the post А для функций, производная которых больше 1 на отрезке, это и гарантия точности по х.

Да.
Но с другой стороны, если производная в корне большая, а эпсилон выбрана такой маленькой, что она близка к машинной точности, то это условие может быть никогда не достигнуто из-за ошибок округления машинных чисел. В результате - бесконечный цикл.


Вернуться в «Computer Science»

Кто сейчас на форуме

Количество пользователей, которые сейчас просматривают этот форум: нет зарегистрированных пользователей и 1 гость