Metoda bisekcji - pomoc w zlokalizowaniu błędu

0

Witam.

Kod, którego tyczy się problem:

double f1(double x)
{
	return (exp(-1.5*x) - 0.3*x*x);
}
double f2(double x)
{
	return (M_PI - x * x + sin(x)) / sqrt(25 - x);
}
double f3(double x)
{
	return (sin(x)*cos(x) + 5 * x + 1);
}

void bisekcja(double a, double b, double eps, double f(double x))
{
	double x0, pierw;
	int k = 0; // k - l. iteracji
	if (f(a) == 0) pierw = a;
	else if (f(b) == 0) pierw = b;

	if (f(a) * f(b) > 0)
	{
		cout << "f nie spelnia zalozenia\n";
	}
	else {
		while (abs(a - b) > eps) {
			k++;
			x0 = (a + b) / 2;
			if (abs(f(x0)) < eps) {
				break;
			}
			else {
				if (f(a)*f(x0) < 0)
				{
					b = x0;
				}
				else
					a = x0;
			}
		}
		pierw = x0;
	}

	cout << "Pierwiastek = " << pierw << endl;
	cout << "Liczba iteracji = " << k << endl;
}







//---------------------------------------------------------
void menu(void)
{
	cout << "\n\n\n\n\n";
	cout << "\t1. Pierwiastek funkcji f1(x) = exp(-1.5*x) - 0.3*x*x" << endl;
	cout << "\t2. Pierwiastek funkcji f2(x) = (M_PI - x*x + sin(x))/sqrt(25 - x)" << endl;
	cout << "\t3. Pierwiastek funkcji f3(x) = sin(x)*cos(x) + 5*x +1" << endl;
	cout << "\t4. Koniec" << endl;
}


//---------------------------------------------------------
void obliczenia(void)
{
	double a, b, eps;
	char z, wybor;
	do
	{
		system("cls");
		menu();
		cout << "\n\n\n\n\n\t\t\t\t\t\tTwoj wybor (1,2,3,4): ";
		wybor = getch();

		system("cls");
		if (wybor == '4')
		{
			cout << "Koniec pracy z programem";
			cout << "Nacisnij dowolny klawisz";
			_getch();
			break;
		}
		else
		{
			cout << "Wybrales funkcje f" << wybor << "(x)\n\n\n";
			cout << "Podaj a: "; cin >> a;
			cout << "Podaj b: "; cin >> b;
			cout << "Podaj dokladnosc eps: "; cin >> eps;
			cout << "\n\n";

			if (wybor == '1' ) {
				bisekcja(a, b, eps, f1);
			}
			else if (wybor == '2') {
				bisekcja(a, b, eps, f2);
			}
			else if (wybor == '3') {
				bisekcja(a, b, eps, f3);
			}

			cout << "Powtarzamy (T/N)? ";
			z = getch();
		}
	} while (z == 'T' || z == 't');
}

Rzecz samego problemu polega na tym, że podczas próby uruchomienia programu z wyborem wzoru f1(x) = exp(-1.5x) - 0.3x*x oraz argumentami kolejno a = 0, b = 1, eps = -2.28 , program wpada w pętlę... Main rozpoczyna pracę od metody obliczenia();

Bardzo prosiłbym o pomoc w zlokalizowaniu błędu (podejrzewam wywołanie funkcji, albo fragment jej treści) oraz ewentualne zastrzeżenia co do bezpieczeństwa samego kodu.

0

Uwzględniłeś to, że jak a i b wartość z funkcji f będzie z jednej strony wykresu np. tylko po dodatniej stronie to się zawiesi?

0

Na wejściu do funkcji powinno być sprawdzenie warunku: f(a) > 0 and f (b) < 0 or f(a) < 0 and f(b) > 0, jak nie to trzeba dobrać inne a, b, gdzie (a < b). Po drugie, Ogranicz liczbę iteracji, jakieś ```n_max`` na wejściu funkcji, a warunek Sprawdzaj w pętli:

if (f(x0) == 0 || (b - a) / 2 < eps)
    return x0;
// dalsza iteracja:
i++; // inkrementacja licznika pętli
// wygenerowanie włąściwego, nowego przedziału:
if (signum(f(x0)) == signum(f(a)) )
    a = x0;
else
    b = x0;
0

Że tak zauważę: używasz funkcji abs - a jest to funkcja operująca na wartościach całkowitych. W tym wypadku podejrzewam, że lepsza byłaby fabs.
Druga rzecz, jak eps może być wartością ujemną?

0

Dziękuję wszystkim za pomoc.
Przyznaję się, że zaniedbałem podstawy teoretyczne tej metody.
Kod funkcjonuje poprawnie (wyświetla oczekiwane wyniki), natomiast dane wprowadzane przez użytkownika były po prostu błędne - nowa wartość eps wynosi 0.00001.

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