zliczanie ilości iteracji w metodzie bisekcji oraz falsi

0

Witam, napisałem program, który oblicza miejsce zerowe funkcji metodą bisekcji oraz falsi. Wstawiłem róznież liczniki (w obu metodach) aby porównać która metoda jest lepsza (wykonuje mniejszą ilość iteracji). niestety po wyswietleniu wyniku dowiaduję się, że funkje wykonały po ok 2 000 obrotów gdzie liczba ta powinna wahać się w granicach co najwyżej kilkudziesięciu. Teraz moja prośba, prosiłbym Was o ponowne wstawienie tych liczników, moze uda się Wam to zrobić, w przeciwnym wypadku czy ta funkcja rzeczywiście wykonuje te 2048 powtórzeń??? z góry dzięki za pomoc.

oto kod:

#include <cstdlib>
#include <iostream>
#include <math.h>
#include "gnuplot_i.hpp"


using namespace std;

int wybor;
string tytul;

float f(float x)
{
   switch(wybor)
   {
        case 1: tytul="x^2-25"; return x*x-25; break;
        case 2: tytul="2*sin(x)"; return 2*sin(x); break;
        case 3: tytul="3*e^x-2"; return 3*exp(x)-2; break;
        case 4: tytul="sin(e^x)"; return sin(exp(x)); break;
   }
}

//TO JEST METODA BISEKCJI

double szukajbisekcja(double lewy, double prawy, double epsilon)
{
   double srodek;
   if(f(lewy)==0)
   return lewy;
   if(f(prawy)==0)
   return prawy;

   while((prawy-lewy)>epsilon)
   {
       srodek=(lewy+prawy)/2.0;

       if (f(srodek)==0) return srodek;
       else
       {
           if (f(lewy)*f(srodek)<0)
           {
               prawy=srodek;
               szukajbisekcja(lewy,prawy,epsilon);
           }
           else
           {
               lewy=srodek;
               szukajbisekcja(lewy,prawy,epsilon);
           }

       }
   }
   
   return srodek;
}

// TO JEST REGUŁA FALSI

double szukajfalsi(double lewy, double prawy, double epsilon)
{
      if(f(lewy)==0)
   return lewy;
   if(f(prawy)==0)
   return prawy;
    
    double x1;

    while((prawy-lewy)>epsilon)
    {
        x1=((lewy*f(prawy))-(prawy*f(lewy)))/(f(prawy)-f(lewy));
        if((f(lewy)*f(x1))<0)
        {
            prawy=x1;
            szukajfalsi(lewy,prawy,epsilon);
        }
        else
        {
            lewy=x1;
            szukajfalsi(lewy,prawy,epsilon);
        }
    }

    return x1;

}

int main()
{
   double a, b, epsilon;

   cout<<"ktory z przykladow chcesz policzyc? \n 1. x^2-25 \n 2. 2*sin(x) \n 3. 3*e^x-2 \n 4. sin(e^x)"<<endl<<endl;
   cin>>wybor;
   cout<<"\nPodaj poczatek przedzialu poszukiwania miejsca zerowego: "; cin>>a;
   cout<<"\nPodaj koniec przedzialu poszukiwania miejsca zerowego: "; cin>>b;
   cout<<"podaj dokladnosc z jaka chcesz otrzymac wynik (epsilon): ";
   cin>>epsilon;

   if (f(a)*f(b)>0) cout<<"funkcja nie spelnia zalozen";
   
   else
   {
        cout<<endl<<endl<<"METODA BISEKCJI "<<endl<<endl;
        cout<<"miejscem zerowym tej funkcji jest x="<<szukajbisekcja(a,b,epsilon)<<endl;
        cout<<endl<<endl<<"REGUŁA FALSI "<<endl<<endl;
        cout<<"miejscem zerowym tej funkcji jest x="<<szukajfalsi(a,b,epsilon)<<endl;
   }

    string tytul2="wykres funkcji f(x)=";
    string tytul3=tytul2+tytul;

   Gnuplot::set_GNUPlotPath("C:\\gnuplot\\binary\\");
   Gnuplot main_plot;

    // Podpisy na wykresie, żeby było wiadomo co na nim widać
    main_plot.set_title( tytul3 );
    main_plot.set_xlabel( "OX" );
    main_plot.set_ylabel( "OY" );

    // styl rysowania wykresu
  main_plot.set_style( "lines" );

  // siatka poprawia czytelność
  main_plot.set_grid();

  // zakres osi x
  main_plot.set_xrange( a-1 , b+1 ) ;

   // funkcja do narysowania
  switch(wybor)
    {
        case 1: main_plot.plot_equation( "x*x-25" , "x^2-25" ); break;
        case 2: main_plot.plot_equation( "2*sin(x)" , "2sin(x)" ); break;
        case 3: main_plot.plot_equation( "3*exp(x)-2" , "3e^x-2" ); break;
        case 4: main_plot.plot_equation( "sin(exp(x))" , "sin(e^x)" ); break;
    }

  // rysowanie miejsc zerowych

  main_plot.set_style( "points" );
  main_plot.set_pointsize( 2.0 );

  vector<double> x( 2 );
  x[ 0 ] = szukajbisekcja(a,b,epsilon);
  x[ 1 ] = szukajfalsi(a,b,epsilon);
  vector<double> y ( 2 );
  y[ 0 ] =  0;
  y[ 1 ] =  0;
  main_plot.plot_xy( x, y, "miejsca zerowe" );

   
   system("pause");
   return 0;
}
0

A gdzie i jak poprzednio te liczniki były? Bo powinny być staticami zdefiniowanymi wewnątrz funkcji.

0

zadeklarowane globalnie i inkrementowane od razu w ciele funkcji.

0

Zacznijmy od tego, że wewnętrzne while w bisekcji i falsi nie są ci w ogóle potrzebne, tylko zaciemniają rekurencje, to samo można zrobić wrzucając jednego if-a a analiza kodu będzie o wiele prostsza. Przyrównywanie doubli do 0 też nie jest dobrym pomysłem.
Nie wiem po co wywaliłeś wspomniane liczniki, poza tym nie podałeś w ogóle dla jakich danych wejściowych wychodzi ci 2000 obrotów. Bez tego raczej nikt nie zgadnie co jest źle.

0

fajne rozwiązanie, można wywalić po dwie linijki i nic nie zmienić (poza polepszeniem)
po grzyba rekurencyjne wywołanie, a weź je wy.... rzuć

1 użytkowników online, w tym zalogowanych: 0, gości: 1