Szukanie miejsc zerowych
Jak to zrobić?
Problem (1)
Problem (2)
Zadanie jest proste:
- Mamy funkcję
ciągłą i taką, że na końcach pewnego przedziału . Zatem, funkcja ta zmienia znak w przedziale (co najmniej raz) ma zatem (co najmniej jedno) miejsce zerowe w tym przedziale. - Przedział
dzielimy na pół (wyznaczając odpowiednio punkt ). - Odrzucamy ten z przedziałów
, w którym funkcja nie zmienia znaku (to znaczy ma ten sam znak na końcach przedziału). - Postępowanie prowadzimy tak długo, aż długość przedziału
będzie mniejsza od zadanej liczby .
Schemat blokowy
Dane
wejściowe
Końce przedziału, w którym funkcja zmienia znak
double A, B;
Dokładność obliczeń
double eps;
robocze
double C;
wyniki
- Współrzędna punktu najbliższa miejscu zerowemu
Co zrobić gdy w zadanym przedziale funkcja znaku nie zmienia?
Ba!
Kod algorytmu
do
{
C = ( A + B ) / 2.;
if ( f(C) == 0 )
// wynikiem jest C
else if ( f(A) * f(C) > 0 )
A = C;
else
B = C;
}while ( fabs(A - B) > eps );
// wynikiem będzie ( A + B ) / 2.;
Jak użyć tego algorytmu?
#include <stdio.h>
int main(int argc, char **argv)
{
double A, B, eps;
A = 1;
B = 2;
eps = 0.001;
double C;
do
{
C = ( A + B ) / 2.;
if ( f(C) == 0 )
// wynikiem jest C
else if ( f(A) * f(C) > 0 )
A = C;
else
B = C;
}while ( fabs(A - B) > eps );
// wynikiem będzie ( A + B ) / 2.;
return 0;
}
Co z funkcją f
?
- Funkcja jednej zmiennej
x
- argument typu zmiennoprzecinkowego
- wynik typu zmiennoprzecinkowego
double f(double x)
{
return exp(x) - sin(x);
}
czyli szukamy rozwiązania problemu
Uwaga
Kod funkcji musimy dodać przed main()
Co to znaczy „wynikiem jest/będzie”?
W miejscu tych komentarzy wydrukujemy podaną wartość
Teraz algorytm „zamkniemy w funkcji”
double pol(double A, double B, double eps)
{
double C;
do
{
C = ( A + B ) / 2.;
if ( f(C) == 0 )
// wynikiem jest C
else if ( f(A) * f(C) > 0 )
A = C;
else
B = C;
}while ( fabs(A - B) > eps );
// wynikiem będzie ( A + B ) / 2.;
}
Co to znaczy „wynikiem jest/będzie”?
W tym miejscu wstawimy polecenie return
(z odpowiednim wyrażeniem)
double pol(double A, double B, double eps)
{
double C;
do
{
C = ( A + B ) / 2.;
if ( f(C) == 0 )
return C;// wynikiem jest C
else if ( f(A) * f(C) > 0 )
A = C;
else
B = C;
}while ( fabs(A - B) > eps );
return ( A + B ) / 2.;// wynikiem będzie ( A + B ) / 2.;
}
Kod programu
#include <math.h>
#include <stdio.h>
double f(double x)
{
return exp(x) - sin(x);
}
double pol(double A, double B, double eps)
{
double C;
do
{
C = ( A + B ) / 2.;
if ( f(C) == 0 )
return C; // wynikiem jest C
else if ( f(A) * f(C) > 0 )
A = C;
else
B = C;
}while ( fabs(A - B) > eps );
return ( A + B ) / 2.; // wynikiem będzie ( A + B ) / 2.;
}
int main(int argc, char **argv)
{
double x;
x = pol(1., 3., 0.00001);
printf("miejscemn zerowym jest %f\n", x);
printf( "wartość funkcji %f\n", f(x) );
return 0;
}
Udoskonalenia kodu
- Co zrobić gdy w pierwszym wywołaniu funkcji
pol()
nie jest spełniony warunek ?
Pojawiły się pomysły, żeby zaraz po wejściu do funkcji sprawdzić ten warunek i:
- Wypisać komunikat „Nie ma miejsc zerowych!”
- Żeby funkcja zwracała wartość
.
Ale oba powyższe pomysły są do nieczego: co będzie gdy miejsce zerowe funkcji wypadnie w punkcie
Można tak
if ( f(A) * f(B) > 0)
return INFINITY;
A po wyjściu z funkcji
x = pol(A, B, eps);
if (x == INFINITY)
printf("Funkcja nie ma miejsc zerowych\n") // lub cokolwiek innego