metoda bisekcji - kod C++

Awatar użytkownika
trawa696
Użytkownik
Użytkownik
Posty: 111
Rejestracja: 18 gru 2009, o 14:14
Płeć: Mężczyzna
Lokalizacja: Gdańsk
Podziękował: 20 razy

metoda bisekcji - kod C++

Post autor: trawa696 »

Witam,
potrzbuje napisac program wyznaczający zera funkcji metoda bisekcji dla funkcji \(\displaystyle{ 2x-tan(x)=0}\) (x rózne od zera). Funkcja ta ma asymptoty w \(\displaystyle{ \frac{\pi}{2}+k\pi, k \in Z}\), jednak kod poniżej uwzglednia te miejsca jako zero, a nie powinien. Nie potrafie tego uwzglednic i bardzo prosze o pomoc.



Oto kod z devC++:

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdlib> 

using namespace std;

const double EPS0 = 0.0000000001; // dokładność porównania z zerem
const double EPSX = 0.0000000001; // dokładność wyznaczenia pierwiastka

double f(double x)
{
  return 2*x - tan (x);
}

int main()
{
  double a,b,x0,x1,fa,fb,f0;

  cout << setprecision(8)     // 8 cyfr po przecinku
       << fixed;              // format stałoprzecinkowy

  cout << "Podaj zakres poszukiwan pierwiastka:

";
  cout << "a = "; cin >> a;
  cout << "b = "; cin >> b;
  fa = f(a); fb = f(b); x1 = a; x0 = b;
  if(fa * fb > 0) cout << "
Funkcja nie spelnia zalozen

";
  else
  {
    while(fabs(x1 - x0) > EPSX)
    {
      x1 = x0;
      x0 = a - fa * (b - a) / (fb - fa);
      f0 = f(x0);
      if(fabs(f0) <= EPS0) break;
      if(fa * f0 < 0)
      {
        b = x0; fb = f0;
      }
      else
      {
        a = x0; fa = f0;
      }
    }
    if(x0==0)
    cout << "
Rozwiazanie nie spelnia zalozen naszego zadania
";
    else
    cout << "
x = " << x0 << endl;
    cout << "
";
  }
  system("pause");
  return 0;
}
Ostatnio zmieniony 25 mar 2011, o 23:17 przez Afish, łącznie zmieniany 1 raz.
Powód: Znaczniki code
spajder
Użytkownik
Użytkownik
Posty: 735
Rejestracja: 7 lis 2005, o 23:56
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 2 razy
Pomógł: 133 razy

metoda bisekcji - kod C++

Post autor: spajder »

Nie masz czego uwzględniać - jednym z założeń tej metody jest ciągłość funkcji w zadanym przedziale \(\displaystyle{ [a,b]}\)
Awatar użytkownika
trawa696
Użytkownik
Użytkownik
Posty: 111
Rejestracja: 18 gru 2009, o 14:14
Płeć: Mężczyzna
Lokalizacja: Gdańsk
Podziękował: 20 razy

metoda bisekcji - kod C++

Post autor: trawa696 »

ale ta funkcja nie jest ciagła na przedziale \(\displaystyle{ (1.5,2)}\) i nie ma tam zera a program oblicza zero dla tego przedzialu, a chciałbym, aby tego nie robil
Ostatnio zmieniony 26 mar 2011, o 16:57 przez trawa696, łącznie zmieniany 1 raz.
Awatar użytkownika
Errichto
Użytkownik
Użytkownik
Posty: 1629
Rejestracja: 17 mar 2011, o 18:55
Płeć: Mężczyzna
Lokalizacja: Suwałki
Podziękował: 28 razy
Pomógł: 272 razy

metoda bisekcji - kod C++

Post autor: Errichto »

Zakres poszukiwań musi być postaci \(\displaystyle{ <EPS-\frac{\pi}{2}+k\pi,-EPS+\frac{\pi}{2}+k\pi>}\) (albo mniejszy)
Możesz ew. podzielić zadany przedział na mniejsze przedziały tak, by te mniejsze nie zawierały asymptot i liczyć dla każdego przedziału oddzielnie.
Awatar użytkownika
trawa696
Użytkownik
Użytkownik
Posty: 111
Rejestracja: 18 gru 2009, o 14:14
Płeć: Mężczyzna
Lokalizacja: Gdańsk
Podziękował: 20 razy

metoda bisekcji - kod C++

Post autor: trawa696 »

nie do konca wiem dlaczego to roziwaze moj problem, a jeszcze mniej jak to ustawic w programie...
spajder
Użytkownik
Użytkownik
Posty: 735
Rejestracja: 7 lis 2005, o 23:56
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 2 razy
Pomógł: 133 razy

metoda bisekcji - kod C++

Post autor: spajder »

Po pierwsze: metoda bisekcji nie działa, jak założenia nie są spełnione w przedziale domkniętym
Po drugie: jak masz punkt \(\displaystyle{ x}\) to możesz wyliczyć:

\(\displaystyle{ k_x = \frac{x}{\pi} + \frac{\pi}{2}}\)

Jak \(\displaystyle{ k_x}\) jest całkowite to trafiłeś w asymptotę, więc wywal program.
W innym wypadku \(\displaystyle{ \lfloor k_x \rfloor}\) można zinterpretować jako identyfikator przedziału, w którym tangens jest określony. Musisz więc wyliczyć takie identyfikatory dla obu krańców przedziałów.
Jak są równe, możesz stosować bisekcję. Jak nie, to wywal program (ewentualnie baw się w znajdowanie pierwiastków w każdym przedziale osobno)
Awatar użytkownika
trawa696
Użytkownik
Użytkownik
Posty: 111
Rejestracja: 18 gru 2009, o 14:14
Płeć: Mężczyzna
Lokalizacja: Gdańsk
Podziękował: 20 razy

metoda bisekcji - kod C++

Post autor: trawa696 »

stworzyłem coś takiego. Nie wiem czy jest to do konca orginalne rozwiazanie, bo odrzucam złe rozwiazanie, chciałbym, zeby w przedziale np [1.5,2] w ktorym funkcja jest nieciagła w ogole nie liczyl zer, czyli zeby najpierw sprawdził ciagłosc funkcji na tym przedziale. Prosze o pomoc

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdlib> 

using namespace std;

const double EPS0 = 0.0000000001; // dokładność porównania z zerem
const double EPSX = 0.0000000001; // dokładność wyznaczenia pierwiastka
const double PI   = 3.1415926536;

double f(double x)
{
  return 2*x - tan (x);
}

int main()
{
  double a,b,d,e,x0,x1,fa,fb,f0;

  cout << setprecision(8)     // 8 cyfr po przecinku
       << fixed;              // format stałoprzecinkowy

  cout << "Podaj zakres poszukiwan pierwiastka:

";
  cout << "a = "; cin >> a;
  cout << "b = "; cin >> b;
  fa = f(a); fb = f(b); x1 = a; x0 = b;
  if(fa * fb > 0) cout << "
Funkcja nie spelnia zalozen

";
  else
  {
    while(fabs(x1 - x0) > EPSX)
    {
      x1 = x0;
      x0 = a - fa * (b - a) / (fb - fa);
      f0 = f(x0);
      if(fabs(f0) <= EPS0) break;
      if(fa * f0 < 0)
      {
        b = x0; fb = f0;
      }
      else
      {
        a = x0; fa = f0;
      }
    }
    d=fabs(((x0/PI)*2));
    e=int (d);
    if(x0==0 || int(d-e)==0)
    cout << "
Rozwiazanie nie spelnia zalozen naszego zadania
";
    else
    cout << "
x = " << x0 << "
" << d << "
" << e << endl;
    cout << "
";
  }
  system("pause");
  return 0;
-- 26 mar 2011, o 21:43 --

By sprawdzic, czy jest ciagła na przedziele stworzylem cos takiego, lecz nie dziala to poprawnie, a wydaje mi sie ze powinno...

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdlib>

using namespace std;

const double PI = 3.1415926536;


double f(double x)
{
return 2*x - tan (x);
}

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

cout << "Podaj zakres poszukiwan pierwiastka:

";
cout << "a = "; cin >> a;
cout << "b = "; cin >> b;
if(a>PI/2)
{
          temp = PI/2+PI;
          while(temp<b){
                        if(temp>a & temp < b)
                        cout << "
funkcja jest nieciagla

";
                        else{
                        temp+=PI;}
                        }
}
else if(b<PI/2)
          {
            temp=PI/2-PI;
            while(temp>a){
            if(temp<a & temp>b)
            cout << "funkcja jest jest jest nieciagła";
             temp-=PI;}
          }
           else
           {     cout << "
funkcja jest NIEciagla

"; //pi/2 lezy w przedziale [a,b]
           }          
system("pause");
return 0;
} 
spajder
Użytkownik
Użytkownik
Posty: 735
Rejestracja: 7 lis 2005, o 23:56
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 2 razy
Pomógł: 133 razy

metoda bisekcji - kod C++

Post autor: spajder »

1. Kompletnie nie rozumiem tej metody, mógłbyś ją jakoś słownie opisać?
2. W c++ logiczne i to

Kod: Zaznacz cały

 
&&
a ni
3. Jak na metodę numeryczną (gdzie liczy się przede wszystkim szybkość wykonania), to jest to masakrycznie niewydajne
ODPOWIEDZ