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
 

Język C++ w fizyce

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ą:

 

obrazek

 

obrazek

 

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:

 

obrazek

 

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

 

obrazek

 

Zatem jego wysokość obliczymy jako:

 

obrazek

 

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

 

obrazek

 

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

 

obrazek

 

Z warunku:

 

obrazek

 

Otrzymujemy funkcję:

 

obrazek

 

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:

 

obrazek

 

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:

 

obrazek

 

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   
im. Kazimierza Brodzińskiego
w Tarnowie

©2024 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

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