Programowanie wprowadzenie

Z Skrypty dla studentów Ekonofizyki UPGOW

WPROWADZENIE

Programowanie komputera to po prostu tworzenie listy poleceń (instrukcji) do wykonania przez mikroprocesor. Taką listę poleceń – sporządzoną według reguł danego języka programowania – nazywamy programem komputerowym. Z biegiem lat powstało bardzo wiele języków programowania, można je z grubsza podzielić na:

  • niskiego poziomu (maszynowe, asemblery). Podzespoły elektroniczne mikroprocesora przetwarzają informacje dostarczane w postaci binarnej (ciągi zer i jedynek). Programowanie w języku maszynowym, czyli na najniższym poziomie symboliki i abstrakcji, polega na dostarczaniu procesorowi rozkazów oraz danych bezpośrednio, w postaci strumienia zer i jedynek. Oto przykład takiego kodu maszynowego:

    111010100000000000001111111111111111100010011101100000000010100000001

Stopień wyżej w hierarchii pojawiają się asemblery. Poszczególnym rozkazom maszynowym odpowiadają określone symbole literowe, tzw. mnemoniki, a nie ciągi liczb. Zastąpienie sekwencji zer i jedynek, reprezentujących rozmaite fragmenty rozkazu maszynowego, przez ich symboliczne nazwy czyni program nieco bardziej czytelny dla człowieka. Spójrzmy na fragmentu kodu w asemblerze:

movw %ax, %fs 
movw %ax, %gs 
lgdt saved_gdt 
lidt saved_idt

Każdy język niskiego poziomu jest związany z danym typem procesora, jego listą rozkazów, architekturą, tak pisane programy niesposób przenosić pomiędzy platformami bazującymi na różnych procesorach. Współcześnie asembler jest wykorzystywany do programowania mikrokontrolerów lub tworzenia niewielkich, wysoce specjalistycznych kodów, wymagających bardzo wysokiej efektywności, programów antywirusowych, itp.

  • wysokiego poziomu (np. Fortran, Pascal, C, C++, Java, Python, C#, Ruby, …). Oferują one instrukcje składające się z słów angielskich, znaków logicznych i operacji matematycznych, zwykle też bibliotekę funkcji standardowych lub klas.

Spójrzmy na kod napisany w jednym z języków wysokiego poziomu:

int suma = 0;
for (int i = 0; i < 6; i = i + 1)
suma = suma + i;

Nawet nie znając tego języka, łatwo się domyślić, że jest to sumowanie liczb całkowitych od zera do 5, tj. po wykonaniu dodawania 0 + 1 + 2 + 3 + 4 + 5 wartość zmiennej suma wynosi, suma = 15. Dzięki bardziej czytelnym instrukcjom, kodowanie algorytmów w języku wysokiego poziomu jest łatwiejsze, przejrzystość programu wzrasta, wygodniej wprowadzac modyfikacje i korygować ewentualne błędy. Zwykle jednej instrukcji języka wysokiego poziomu odpowiada od kilku do kilkunastu elementarnych rozkazów asemblera. Pomimo różnic pomiędzy poszczególnymi językami wysokiego poziomu, w każdym z nich występuje niewielka grupa instrukcji podstawowych, służących do sterowania przebiegiem programu. Omówię je, wraz z przykładami, w pierwszym rozdziale skryptu. Oprócz języków niskiego lub wysokiego poziomu pojawiły się zintegrowane pakiety obliczeniowo-programistyczne (np. Maple, MATHEMATICA, MATLAB, LabVIEW, ...). Od strony formalnej, to programy komputerowe, napisane w języku wysokiego poziomu. Na przykład kod źródłowy pakietu MATLAB początkowo był pisany w Fortranie, obecnie jego kolejne wersje przygotowuje się za pomocą C/C++. Pakiety te są jednak tak zaawansowane, iż spełniają nie tylko rolę potężnego hiperkalkulatora, ale umożliwiają również programowanie. Oferują one bardzo szeroką paletą instrukcji symbolicznych, ułatwiających intuicyjne wykonywanie zadań, programista bardziej skupia się na tym „co robić ?” (task oriented programing), niż „jak robić ?”. Jedna instrukcja symboliczna pakietu potrafi uruchomić bardzo skomplikowany algorytm (kaskadę algorytmów), który w rodzimym języku wysokiego poziomu (np. C++) zajmuje niekiedy dziesiątki czy nawet setki linii kodu. Dla ilustracji, kilka instrukcji z pakietu/programu MATHEMATICA®:

  • chcąc numerycznie obliczyć całkę oznaczoną z funkcji f(x) = sin[sin(x)] w przedziale < 0, 2> piszemy tylko jedną symboliczną instrukcję:
    Inp[1]=NIntegrate[Sin[Sin[x]],{x,0,2}]
  • w celu znalezienia liczbowych wartości pierwiastków równania piątego stopnia x5 -2 x + 3 = 0 wystarczy wydać polecenie
    Inp[2]=NSolve[x^5 -2 x + 5 = = 0, x]
  • jak wiadomo, operacja odwracania macierzy jest dość uciążliwa. Tutaj pojedyncza komenda:
    Inp[3]=Inverse[ {1, 2, 3}, {4, 2, 2}, {5, 1, 7} ]
    od razu tworzy macierz odwrotną do macierzy wyjściowej

    \(\begin{bmatrix} 1 & 2 & 3 \\ 4 & 2 & 2 \\ 5 & 1 & 7\end{bmatrix}\)

  • przebieg funkcji f(x) = x3 sin(3 x) cos(x/2) exp(-x) nie jest oczywisty. Po uruchomieniu instrukcji

    Inp[4]=Plot[ x^3 Sin[4 x] Cos[x/2] Exp[-x], {x, 0, 2 Pi}]

    wykres f(x) dla zmiennej x leżącej w przedziale < 0, 2π > pojawi się na ekranie komputera
    Pwf1.jpg