TI/Algorytm: Różnice pomiędzy wersjami

Z Brain-wiki
(Utworzono nową stronę " ==Jak to działa: algorytm → kod źródłowy → program wykonywalny== Pisząc '''program komputerowy''', chcemy stworzyć coś, co będzie zrozumiałe dla k...")
 
 
(Nie pokazano 33 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 1: Linia 1:
  
==Jak to działa: algorytm → kod źródłowy → program wykonywalny==
+
==[[Technologie informacyjne i komunikacyjne|⬆]] Algorytm → kod źródłowy → program wykonywalny==
  
Pisząc '''program komputerowy''', chcemy stworzyć coś, co będzie zrozumiałe dla komputera, i będzie pewnego rodzaju instrukcją, opisem tego, co komputer ma wykonywać, często zawierającą w sobie wiele różnorodnych i skomplikowanych funkcjonalności. Programem komputerowym jest np. przeglądarka internetowa, edytor tekstów, odtwarzacz multimediów, czy też prosta aplikacja kalkulatora.  
+
Pisząc '''program komputerowy''', chcemy stworzyć coś, co będzie zrozumiałe dla komputera, i będzie pewnego rodzaju instrukcją — dokładnym i jednoznacznym opisem tego, co komputer ma wykonywać. Programem komputerowym jest np. przeglądarka internetowa, edytor tekstów, odtwarzacz multimediów, czy też prosta aplikacja kalkulatora.  
  
Aby się dowiedzieć jak w ogóle możemy powiedzieć komputerowi co ma zrobić, powiedzmy sobie w jaki sposób możemy wpływać na to co komputer robi.
+
<!--
 
+
Jak opisać komputerowi skomplikowany zbiór funkcjonalności, jakich dostarcza np. przeglądarka internetowa, skoro maszyna rozumie bezpośrednio jedynie bardzo ograniczony zbiór prostych instrukcji procesora? Pisanie wszystkiego za pomocą prostych instrukcji procesora trwałoby bezsensownie długo. Z pomocą przychodzą języki programowania, w których które analizując treść programów sprowadzają je z postaci bardziej intuicyjnej dla człowieka do postaci zrozumiałej dla maszyny.
Zatem w jaki sposób opisać komputerowi taki skomplikowany zbiór funkcjonalności jakie dostarcza np przeglądarka internetowa, skoro maszyna rozumie bezpośrednio jedynie bardzo ograniczony zbiór prostych instrukcji procesora? Pisanie wszystkiego za pomocą prostych instrukcji procesora trwałoby jakoś nieskończenie długo. Z pomocą przychodzi nam cała hierarchia różnorodnych języków programowania, z których jedne potrafią "parsować", inne, analizując słowo po słowie treść programów w nich zapisanych i sprowadzając z postaci bardziej intuicyjnej dla człowieka do postaci zrozumiałej dla maszyny.
+
-->
 +
Człowiek pisze tekst programu komputerowego zgodnie z regułami wybranego języka programowania. Tworzy w ten sposób kod źródłowy. Aby go uruchomić, należy, zależnie od wybranego języka:
 +
*skompilować kod źródłowy do kodu maszynowego, zrozumiałego dla komputera, czyli użyć programu, zwanego kompilatorem (stworzonego dla tego konkretnego języka, w którym program napisano), który potrafi wczytać kod źródłowy i zgodnie z gramatyką danego języka programowania przetworzyć na kod maszynowy, który będzie tzw. "programem wykonywalnym". Żeby używać programu w takiej postaci nie potrzebujemu już kodu żródłowego. Wystarczy postać wykonywalna. Mówimy wtedy o '''kompilowanych językach programowania'''.
 +
*użyć do wykonania napisanego przez siebie kodu "interpretera" (np. Pythona). Mówimy wtedy o '''językach interpretowanych'''. Tym, co uruchamiamy za każdym razem, jest napisany przez nas kod źródłowy, ale żeby komputer mógł go zrozumieć, używamy interpretera danego języka — programu, który analizuje kod źródłowy i od razu go wykonuje. Takie rozwiązanie jest zwykle nieco wolniejsze i pochłania więcej zasobów, niż uruchamianie skompilowanego wcześniej kodu maszynowego. Jednak do pewnych zastosowań języki interpretowane, zwane też skryptowymi, są wygodniejsze niż kompilowane. Szczególnie, gdy kod źródłowy jest często zmieniany — nie musimy za każdym razem go kompilować i uruchamiać kodu maszynowego. Tak jest np. w przypadku Pythona, którego uczycie się na ćwiczeniach.  
  
Człowiek pisze program komputerowy zgodnie z jakimś językiem programowania. Tworzy w ten sposób kod źródłowy. Chcąc by komputer go wykonał, ma dwa wyjścia:
+
Przyjrzyjmy się, co właściwie znajduje się w kodzie źródłowym. Najczęściej jest to ciąg instrukcji, opisującym bardzo
*skompilować go do kodu maszynowego, zrozumiałego dla komputera, czyli użyć programu, zwanego kompilatorem (tego konkretnego języka, w którym Człowiek napisał program), który potrafi wczytać kod źródłowy i zgodnie z gramatyką danego języka programowania przetworzyć na kod maszynowy, który będzie naszym "programem wykonywalnym". Wtedy żeby używać programu, nie potrzebujemu już więcej, po skompilowaniu, jego kodu żródłowego. Wystarczy nam postać "wykonywalna". Mówimy wtedy o '''językach programowania kompilowanych'''.
+
dokładnie jakiś algorytm schemat postępowania. Na przykład algorytm otwierania drzwi mógłby wyglądać tak:
*użyć do wykonania napisanego przez siebie kodu "interpretera". Mówimy wtedy o '''językach interpretowanych'''. Tym co uruchamiamy jest za każdym razem stworzony przez nas kod źródłowy, ale żeby komputer mógł go zrozumieć, używamy interpretera danego języka &mdash; programu, który analizuje kod źródłowy i od razu go wykonuje. Takie rozwiązanie jest wolniejsze i pochłaniające więcej zasobów, niż uruchamianie wcześniej stworzonego kodu maszynowego, jednak do pewnych zastosowań języki interpretowane, zwane też skryptowymi są bardizej wskazane niż kompilowane. Szczególnie gdy kod źródłowy jest często zmieniany i wykonywany w innej formi &mdash; nie ma sensu za każdym razem go przekompilowywać, i uruchamiać kodu maszynowego. Tak jest np. w przypadku pythona którego się uczycie na ćwiczeniach. Języki skryptowe przydają sie więc np do zastosowań naukowo-badawczych.
 
 
 
Teraz przyjrzyjmy się, co właściwie piszemy w takim kodzie
 
źródłowym. Najczęściej jest to ciąg instrukcji, opisującym bardzo
 
dokładnie jakiś algorytm &mdash; schemat postępowania. Na przykład
 
algorytm otwierania drzwi mógłby wyglądać tak:
 
  
 
   naciśnij klamkę
 
   naciśnij klamkę
Linia 29: Linia 26:
 
'''Program komputerowy''' to zapis algorytmu w języku zrozumiałym dla
 
'''Program komputerowy''' to zapis algorytmu w języku zrozumiałym dla
 
komputera. Ten język składa się niestety z samych zer i jedynek
 
komputera. Ten język składa się niestety z samych zer i jedynek
(wyjaśnienie w następnym rozdziale) i nie jest dla ludzi wygodny w
+
i nie jest dla ludzi wygodny w
 
użyciu. Dlatego do pisania programów komputerowych stworzono języki
 
użyciu. Dlatego do pisania programów komputerowych stworzono języki
programowania (Ada, C, Pascal, Fortran, Logo, Basic... Python :-) ).
+
programowania (Ada, C, C++, Java, Pascal, Fortran, Logo, Basic, Rust... Python :-) ).
  
 
Tekst programu (czyli kod źródłowy) podlega ścisłej gramatyce i
 
Tekst programu (czyli kod źródłowy) podlega ścisłej gramatyce i
 
ortografii danego języka &mdash; zamiana jednej litery zwykle
 
ortografii danego języka &mdash; zamiana jednej litery zwykle
spowoduje, że program nie będzie działał. To znaczy zwykle nawet nie
+
spowoduje, że program nie będzie działał zwykle nawet nie
 
da się go ''skompilować''.
 
da się go ''skompilować''.
  
===Przykład: kod źródłowy programu obliczającego silnię w języku C===
+
====Kod źródłowy programu obliczającego silnię w języku Python====
 +
<source lang="Python">
 +
liczba = 1
 +
wynik = 1
 +
while liczba < 5:
 +
liczba += 1
 +
wynik *= liczba
 +
print('Python: 5! =', wynik)
 +
</source>
 +
 
 +
====Kod źródłowy programu obliczającego silnię w języku C====
 
<source lang="c">
 
<source lang="c">
 
#include <stdio.h>
 
#include <stdio.h>
Linia 49: Linia 56:
 
       wynik = wynik*liczba;
 
       wynik = wynik*liczba;
 
   }
 
   }
   printf("5! =  %ld\n", wynik);
+
   printf("C: 5! =  %ld\n", wynik);
  
 
   return 0;
 
   return 0;
Linia 55: Linia 62:
 
</source>
 
</source>
  
===Przykład: kod źródłowy programu obliczającego silnię w języku C++===
+
====Kod źródłowy programu obliczającego silnię w języku C++====
 
<source lang="c">
 
<source lang="c">
 +
//g++
 
#include <iostream>  
 
#include <iostream>  
 
using namespace std;
 
using namespace std;
Linia 67: Linia 75:
 
     wynik = wynik*liczba;
 
     wynik = wynik*liczba;
 
   }
 
   }
   cout << "5! = "<< wynik << endl
+
   cout << "C++: 5! = "<< wynik << endl;
        <<"obliczone programem w C++ :-)" << endl;
 
 
}
 
}
 
</source>
 
</source>
  
===Przykład: kod źródłowy programu obliczającego silnię w języku Java===
+
====Kod źródłowy programu obliczającego silnię w języku Java====
 
<source lang="java">
 
<source lang="java">
class Silnia {
+
//javac s.java; java s
 +
class s {
 
   public static void main(String[] args) {
 
   public static void main(String[] args) {
 
       int wynik=1, liczba=1;
 
       int wynik=1, liczba=1;
Linia 82: Linia 90:
 
         wynik=wynik*liczba;
 
         wynik=wynik*liczba;
 
       }
 
       }
       System.out.println(wynik);
+
       System.out.println("Java: 5! = " + wynik);
 
   }
 
   }
 
}
 
}
 
</source>
 
</source>
Taki sposób programowania, w którym komputerowi przekazujemy po prostu
+
 
kolejno instrukcje jakie ma wykonać, używamy często kontrukcji typu
 
pętla, wielu iteracyjnych powtorzeń, nazywamy '''programowaniem imperatywnym''', a języki do tego stworzene językami
 
imperatywnymi. Stanowią bardzo szeroką grupę wśród języków
 
programowania, ale nie jedyną. Istnieją też języki przystosowane do
 
innego sposobu opisywania zadania. Np. języki deklaratywne &mdash;
 
zamiast sposobu dojścia do rozwiązania które ma być wynikiem działania
 
programu, czyli zamiast ciągu instrukcji, opisujemy tylko samo
 
rozwiązania. Mówimy jedynie co ma być zrobione, nie wnikając już w to
 
jak. W tych językach ciężar sposobu rozwiązania jest przerzucony na
 
kompilator. Wydawałoby się, że do dla człowieka wygodniejsze, nie musi
 
sam myśleć jak ma zostać znalezione rozwiązanie, wystarczy opisać
 
dokładnie jaki jest problem. Jednak okazuje się to często znacznie
 
mniej intuicyjne i wymagające bardziej abstrakcyjnego myślenia i
 
często nastręcza więcej problemów.
 
  
 
Kompilacja to zamiana kodu źródłowego na binarny (tj. zera i jedynki),
 
Kompilacja to zamiana kodu źródłowego na binarny (tj. zera i jedynki),
Linia 119: Linia 113:
 
Nawet dziś fachowcy uważają, że nie ma większych programów całkowicie
 
Nawet dziś fachowcy uważają, że nie ma większych programów całkowicie
 
wolnych od błędów. Testowanie programów (czyli wykrywanie błędów) jest
 
wolnych od błędów. Testowanie programów (czyli wykrywanie błędów) jest
co najmniej tak samo kosztowne i pracochłonne jak ich pisanie. Stąd
+
co najmniej tak samo kosztowne i pracochłonne jak ich pisanie.  
pojawiające się często darmowe "wersje beta", czyli programy nie
+
Niestety konkutencja na rynku oprogramowania wymusza przedwczesne wypuszczanie na rynek niewystarczająco przetestowanych programów. Dlatego niemal przyzwyczailiśmy się do faktu, że programy czasem "wieszają się" lub nie działają tak, jak powinny. Ale znacznie niebezpieczniejsze jest niedostateczne testowanie programów, w tym przede wszystkim systemów operacyjnych, pod kątem bezpieczeństwa. Powoduje to istnienie luk, które mogą być wykorzystane przez cybeprpzestępców do wykradania danych a nawet przejećia (zdalnie) całkowitej kontroli nad naszym komputerem, który może być w takiej sytuacji wykorzystywany do dalszych przestępstw i ataków.
przetestowane do końca &mdash; ich udostępnianie wiązane jest z
 
nadzieją, że resztę błędów znajdą użytkownicy.
 
  
Coraz większego znaczenia nabiera idea "otwartych źródeł", według
+
Coraz większego znaczenia nabiera idea [[TI/Otwarte_Źródła,_GNU_i_wolność_oprogramowania|Otwartych Źródeł]] (ang. ''Open Source''), według której każdy użytkownik ma prawo wglądu w kod źródłowy
której każdy użytkownik powinien mieć prawo wglądu w kod źródłowy
 
 
programu, którego używa, a nawet jego modyfikacji, czyli dostosowania
 
programu, którego używa, a nawet jego modyfikacji, czyli dostosowania
 
do własnych potrzeb. Jednak w przypadku komercyjnych programów i
 
do własnych potrzeb. Jednak w przypadku komercyjnych programów i
Linia 131: Linia 122:
 
tajemnicą producenta, a użytkownik dostaje wyłącznie programy
 
tajemnicą producenta, a użytkownik dostaje wyłącznie programy
 
wykonywalne (czyli zera i jedynki).
 
wykonywalne (czyli zera i jedynki).
 +
 +
'''Ciekawostka''': ''wyjście programu w Uniksie można w prosty sposób przekierować do pliku''
 +
<source lang="bash">
 +
% ls
 +
silnia.py
 +
% python3 silnia.py
 +
Python obliczył: 5! = 720
 +
% python3 silnia.py > wynik.txt
 +
% ls
 +
silnia.py wynik.txt
 +
% cat wynik.txt
 +
Python obliczył: 5! = 720
 +
</source>
 +
 +
<!--
 +
==Bramki logiczne w serialu "Three Body Problem"==
 +
https://youtu.be/icnQ2Fu2mZQ?si=GKh9QRh7pmhBFxF-&t=189
 +
-->
 +
 +
 +
<div align="right">
 +
[[TI/Zera i jedynki|⬅]]  [[Technologie informacyjne i komunikacyjne|⬆]]  [[TI/Uczenie_maszynowe|⮕]]
 +
</div>

Aktualna wersja na dzień 15:57, 17 paź 2024

Algorytm → kod źródłowy → program wykonywalny

Pisząc program komputerowy, chcemy stworzyć coś, co będzie zrozumiałe dla komputera, i będzie pewnego rodzaju instrukcją — dokładnym i jednoznacznym opisem tego, co komputer ma wykonywać. Programem komputerowym jest np. przeglądarka internetowa, edytor tekstów, odtwarzacz multimediów, czy też prosta aplikacja kalkulatora.

Człowiek pisze tekst programu komputerowego zgodnie z regułami wybranego języka programowania. Tworzy w ten sposób kod źródłowy. Aby go uruchomić, należy, zależnie od wybranego języka:

  • skompilować kod źródłowy do kodu maszynowego, zrozumiałego dla komputera, czyli użyć programu, zwanego kompilatorem (stworzonego dla tego konkretnego języka, w którym program napisano), który potrafi wczytać kod źródłowy i zgodnie z gramatyką danego języka programowania przetworzyć na kod maszynowy, który będzie tzw. "programem wykonywalnym". Żeby używać programu w takiej postaci nie potrzebujemu już kodu żródłowego. Wystarczy postać wykonywalna. Mówimy wtedy o kompilowanych językach programowania.
  • użyć do wykonania napisanego przez siebie kodu "interpretera" (np. Pythona). Mówimy wtedy o językach interpretowanych. Tym, co uruchamiamy za każdym razem, jest napisany przez nas kod źródłowy, ale żeby komputer mógł go zrozumieć, używamy interpretera danego języka — programu, który analizuje kod źródłowy i od razu go wykonuje. Takie rozwiązanie jest zwykle nieco wolniejsze i pochłania więcej zasobów, niż uruchamianie skompilowanego wcześniej kodu maszynowego. Jednak do pewnych zastosowań języki interpretowane, zwane też skryptowymi, są wygodniejsze niż kompilowane. Szczególnie, gdy kod źródłowy jest często zmieniany — nie musimy za każdym razem go kompilować i uruchamiać kodu maszynowego. Tak jest np. w przypadku Pythona, którego uczycie się na ćwiczeniach.

Przyjrzyjmy się, co właściwie znajduje się w kodzie źródłowym. Najczęściej jest to ciąg instrukcji, opisującym bardzo dokładnie jakiś algorytm — schemat postępowania. Na przykład algorytm otwierania drzwi mógłby wyglądać tak:

 naciśnij klamkę
 jeśli drzwi się otworzą
    udało się - koniec.
 w przeciwnym razie
    włóż do zamka klucz, przekręć w lewo i naciśnij klamkę
    jeśli drzwi się otworzą
       udało się - koniec.
    w przeciwnym razie
       nie udało się - koniec.

Program komputerowy to zapis algorytmu w języku zrozumiałym dla komputera. Ten język składa się niestety z samych zer i jedynek i nie jest dla ludzi wygodny w użyciu. Dlatego do pisania programów komputerowych stworzono języki programowania (Ada, C, C++, Java, Pascal, Fortran, Logo, Basic, Rust... Python :-) ).

Tekst programu (czyli kod źródłowy) podlega ścisłej gramatyce i ortografii danego języka — zamiana jednej litery zwykle spowoduje, że program nie będzie działał — zwykle nawet nie da się go skompilować.

Kod źródłowy programu obliczającego silnię w języku Python

liczba = 1
wynik = 1
while liczba < 5:
	liczba += 1
	wynik *= liczba
print('Python: 5! =', wynik)

Kod źródłowy programu obliczającego silnię w języku C

#include <stdio.h>
int main()
{
   long int wynik=1, liczba=1;

   while (liczba < 5) {
      liczba = liczba+1;
      wynik = wynik*liczba;
   }
   printf("C: 5! =  %ld\n", wynik);

   return 0;
}

Kod źródłowy programu obliczającego silnię w języku C++

//g++
#include <iostream> 
using namespace std;
int main()
{
   long liczba=1, wynik=1;

   while (liczba < 5) {
     liczba = liczba + 1;
     wynik = wynik*liczba;
   }
   cout << "C++: 5! = "<< wynik << endl;
}

Kod źródłowy programu obliczającego silnię w języku Java

//javac s.java; java s
class s {
   public static void main(String[] args) {
      int wynik=1, liczba=1;

      while(liczba<5){
         liczba=liczba+1;
         wynik=wynik*liczba;
      }
      System.out.println("Java: 5! = " + wynik);
  }
}


Kompilacja to zamiana kodu źródłowego na binarny (tj. zera i jedynki), wykonywalny przez komputer. Dokonuje tego program komputerowy zwany kompilatorem. Jeśli "nie zrozumie" jakiegoś słowa w kodzie źródłowym, bo np. end zamieniliśmy na edn, to po prostu odmówi kompilacji.

Niestety zdarzają się również błędy, które przechodzą przez proces kompilacji, ale powodują, że skompilowany program nie działa dokładnie według intencji autora. Takie błędy bywają trudne do wyśledzenia, szczególnie, gdy ujawniają się tylko np. w rzadko używanych funkcjach i w specyficznych sytuacjach. Mówi się o nich bugs (insekty, robaki). Nazwa pochodzi z czasów pierwszych komputerów, budowanych na lampach i zajmujących ogromne pomieszczenia. Ich programowanie polegało na przełączaniu kabelków, a zwarcia (czyli błędy) powodowały czasem ginące wśród nich ćmy.

Nawet dziś fachowcy uważają, że nie ma większych programów całkowicie wolnych od błędów. Testowanie programów (czyli wykrywanie błędów) jest co najmniej tak samo kosztowne i pracochłonne jak ich pisanie. Niestety konkutencja na rynku oprogramowania wymusza przedwczesne wypuszczanie na rynek niewystarczająco przetestowanych programów. Dlatego niemal przyzwyczailiśmy się do faktu, że programy czasem "wieszają się" lub nie działają tak, jak powinny. Ale znacznie niebezpieczniejsze jest niedostateczne testowanie programów, w tym przede wszystkim systemów operacyjnych, pod kątem bezpieczeństwa. Powoduje to istnienie luk, które mogą być wykorzystane przez cybeprpzestępców do wykradania danych a nawet przejećia (zdalnie) całkowitej kontroli nad naszym komputerem, który może być w takiej sytuacji wykorzystywany do dalszych przestępstw i ataków.

Coraz większego znaczenia nabiera idea Otwartych Źródeł (ang. Open Source), według której każdy użytkownik ma prawo wglądu w kod źródłowy programu, którego używa, a nawet jego modyfikacji, czyli dostosowania do własnych potrzeb. Jednak w przypadku komercyjnych programów i systemów operacyjnych kod źródłowy bywa wciąż pilnie strzeżoną tajemnicą producenta, a użytkownik dostaje wyłącznie programy wykonywalne (czyli zera i jedynki).

Ciekawostka: wyjście programu w Uniksie można w prosty sposób przekierować do pliku

 % ls
 silnia.py
 % python3 silnia.py 
 Python obliczył: 5! = 720
 % python3 silnia.py > wynik.txt
 % ls
 silnia.py	wynik.txt
 % cat wynik.txt 
 Python obliczył: 5! = 720