![]() |
Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2010 mgr
Jerzy Wałaszek
|
Materiały pomocnicze:
Wprowadzenie do C++ -
strumienie cout i cin, zmienne
Instrukcja przypisania, modyfikacja zmiennej
Instrukcja warunkowa if
Pętle warunkowe
Pętla iteracyjna
Liczby rzeczywiste i ich własności
Miejsca zerowe funkcji
Na wysokości h umieszczono działo z lufą skierowaną poziomo. Z działa oddajemy strzał. Pocisk opuszcza lufę działa z prędkością V i uderza we wzgórze, którego zbocze zdefiniowane jest funkcją:


Dla danych h, V wyznaczyć punkt xo zderzenia pocisku ze wzgórzem. Pominąć wszelkie opory ruchu. Przyjąć stałe przyspieszenie grawitacyjne g = 9,81 [m/s2].
Jest to przypadek rzutu poziomego. Ruch odbywa się w dwóch kierunkach. W kierunku poziomym na pocisk nie działa żadna siła, zatem ruch jest jednostajny ze stałą prędkością V. W kierunku pionowym działa siła przyciągania grawitacyjnego Ziemi, zatem ruch jest jednostajnie przyspieszony. W trakcie ruchu pocisk obniża swoją wysokość hP. Z drugiej strony wzgórze wraz ze wzrostem x powiększa swoją wysokość hW. W pewnej odległości xo wysokość pocisku hP zrówna się z wysokością wzgórza hW, nastąpi zderzenie. Naszym zadaniem jest wyznaczenie tego punktu.
Aby rozwiązać to zadanie, musimy wyznaczyć wysokość wzgórza hW oraz wysokość pocisku hP w zależności od x.
Ponieważ wzgórze opisane jest funkcją, otrzymujemy bezpośrednio:

W kierunku pionowym pocisk wykonuje spadek swobodny, pokonując drogę:

Zatem jego wysokość obliczymy jako:

Czas ruchu t nie jest dany, lecz obliczymy go łatwo ze wzorów na drogę w kierunku poziomym:

Wzór na czas wstawiamy do wzoru na wysokość pocisku hP:

Z warunku:

Otrzymujemy funkcję:

Funkcja f(x) przyjmuje wartość 0 dla xo, w którym wysokość pocisku i wzgórza jest taka sama. Wartość xo znajdziemy metodą regula falsi. W metodzie tej musimy określić przedział poszukiwań pierwiastka. Dla naszego zadania będzie to przedział <a,b> zawierający punkt xo. Punkt a otrzymujemy bez liczenia:

Natomiast punkt b niech będzie odległością rzutu poziomego - czyli odległością, w jakiej pocisk przeciąłby oś OX, gdyby nie było wzgórza. Ponieważ wzgórze jest, to punkt xo pojawi się wcześniej. Punkt b to droga w kierunku poziomym, jaką pokona pocisk w czasie spadku swobodnego z wysokości h:

Mamy już wszystkie niezbędne wzory do napisania naszego programu.
// Rozwiązanie problemu rzutu poziomego na wzgórze
// (C)2010 I LO w Tarnowie
//------------------------------------------------
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
// Zmienne globalne
//-----------------
const double EPS = 0.00001; // dokładność wyznaczenia x0
const double g = 9.81; // przyspieszenie grawitacyjne Ziemi
double h,V; // wysokość, prędkość początkowa pocisku
// Tutaj definiujemy naszą funkcję
//--------------------------------
double f(double x)
{
return h - g * x * x / 2 / V / V - 0.00001 * (sqrt(x) + x * x * x);
}
int main()
{
double a,b,x0,fa,fb,f0;
cout << fixed << setprecision(4);
cout << "WYZNACZANIE ZASIEGU STRZALU\n"
"---------------------------\n\n";
// wczytujemy dane wejściowe
cout << "h = "; cin >> h;
cout << "V = "; cin >> V;
cout << endl;
// obliczamy przedział <a,b>
a = 0;
b = V * sqrt(2 * h / g);
// obliczamy wartości funkcji w punktach a i b
fa = f(a);
fb = f(b);
// sprawdzamy, czy na krańcach funkcja ma różne znaki
if(fa * fb < 0)
{
// pierwiastka szukamy metodą regula falsi
while(true)
{
x0 = a - fa * (b - a) / (fb - fa);
f0 = f(x0);
// sprawdzamy, czy x0 jest przybliżonym pierwiastkiem
if(fabs(f0) < EPS)
{
cout << "x0 = " << x0 << endl << endl;
break; // pierwiastek znaleziony, przerywamy pętlę
}
// za nowy przedział przyjmujemy podprzedział, w którym funkcja zmienia znak
if(fa * f0 < 0)
{
b = x0; fb = f0;
}
else
{
a = x0; fa = f0;
}
}
}
else cout << "NIEPRAWIDLOWE DANE\n\n";
return 0;
}
|
![]() | I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe