Języki
Język maszynowy (kod maszynowy) – język programowania, w którym zapis programu wymaga instrukcji bezpośrednio jako liczb, które są rozkazami i danymi bezpośrednio pobieranymi przez procesor wykonujący ten program.
Kod maszynowy może być generowany w procesie kompilacji (w przypadku języków wysokiego poziomu) lub asemblacji (w przypadku asemblera). W trakcie procesu tworzenia kodu maszynowego tworzony jest często kod pośredni, który może być zapisywany w pliku o odpowiednim formacie. Kod pośredni poddawany jest linkowaniu, które wygeneruje ostateczny obraz programu w taki sposób, że system operacyjny będzie mógł go wczytać, z ewentualnym dostosowaniem argumentów będących adresami do adresów odpowiednich bloków programu w pamięci, i wykonać zawarte w nim instrukcje. Ponieważ każdy typ procesora ma swój własny język maszynowy, jest to najmniej przenośny język programowania.
Asembler (z ang. assembler) – termin informatyczny związany z programowaniem i tworzeniem kodu maszynowego dla procesorów. W języku polskim oznacza on program tworzący kod maszynowy na podstawie kodu źródłowego (tzw. asemblacja) wykonanego w niskopoziomowym języku programowania bazującym na podstawowych operacjach procesora zwanym językiem asemblera, popularnie nazywanym również asemblerem.
Język wysokiego poziomu (autokod) – typ języka programowania, którego składnia i słowa kluczowe mają maksymalnie ułatwić rozumienie kodu programu dla człowieka, tym samym zwiększając poziom abstrakcji i dystansując się od sprzętowych niuansów. Kod napisany w języku wysokiego poziomu nie jest bezpośrednio „zrozumiały” dla komputera – większość kodu stanowią tak naprawdę normalne słowa, np. w języku angielskim. Aby umożliwić wykonanie programu napisanego w tym języku należy dokonać procesu kompilacji.
Przykładowe typy danych[edytuj]
Przykładowe typy występujące w wielu językach programowania:
typ całkowity (w C, C++, Javie np. int, w Pascalu np. integer) – typ reprezentujący liczbę całkowitą z jakiegoś zakresu zależnego od języka a nawet konkretnej implementacji.
typ zmiennoprzecinkowy (w C, C++, Javie np. double, w Pascalu np. real) – typ reprezentujący przybliżoną wartość liczby rzeczywistej.
typ stałopozycyjny (w PL/1, Cobol – typ reprezentujący liczbę wymierną o stałym mianowniku.
typ znakowy (w C, C++, Javie, Pascalu np. char) – typ reprezentujący pojedynczy znak (ASCII lub w nowszych implementacjach Unicode)
typ tekstowy (w Javie string, w C++, Pascalu np. string) – typ reprezentujący cały tekst. W C jego rolę pełni wskaźnik do literału znakowego – const char*
typ wskaźnikowy – oznacza wskaźnik na zmienną zadanego typu.
typ referencyjny – odmiana wskaźnika, referencja jest różnie pojmowana w poszczególnych językach.
typ wyliczeniowy – typ mogący przyjmować jedną z zadanych symbolicznych wartości, np. (czerwony, zielony, niebieski)
typ tablicowy – ciąg zmiennych zadanego typu indeksowanych liczbą naturalną z pewnego przedziału (w większości języków programowania) lub dowolnym unikalnym kluczem który może być zarówno liczbą jak i ciągiem znaków (w PHP)
typ strukturalny – zespół połączonych w jedną całość zmiennych zwanych polami struktury. Do każdego pola można się odwoływać oddzielnie.
klasa (typ obiektowy) – odmiana struktury, w której oprócz zespołu danych dodane są także procedury działających na tych danych. Zmienna typu klasy nazywa się obiektem. Pojęcie klasy spowodowało powstanie nowego paradygmatu programowania, zwanego programowaniem obiektowym i zrewolucjonizowało sposób myślenia programisty, który od tej pory patrzy na program jako na zbiór autonomicznych obiektów.
typ pusty (np. void w C i C++) – występuje np. w oznaczaniu funkcji nie zwracających żadnych wartości.
typ logiczny (np. bool w C++) – może przyjmować wartości logiczne 1 (true, t) lub 0 (false, nil).
typ bitowy reprezentujący ciąg bitów, (np. '01101'B – PL/I).
typ zbiorowy reprezentujący zbiory elementów (np. [pon, wt, sr, czw, pt] – Pascal).
typ zespolony reprezentujący liczby zespolone.
typ etykietowy reprezentujący wartości będące etykietami instrukcji, wskazaniami instrukcji.
Języki interpretowane to języki programowania, które zazwyczaj implementowane są w formie interpretera, a nie kompilatora. Teoretycznie każdy język może być kompilowany i interpretowany, dlatego rozróżnienie to polega na najczęściej stosowanych rozwiązaniach, a nie zależy od cech samego języka. Program w języku interpretowanym nie jest kompilowany, lecz jest przechowywany w postaci kodu źródłowego i dopiero podczas uruchomienia wczytywany, interpretowany i wykonywany przez interpreter języka.
Języki interpretowane ułatwiają pisanie programów przenośnych, czyli zgodnych z wieloma systemami operacyjnymi.
Przykładowe języki interpretowane to:
Bash
Maxima
Perl
Python
Ruby
JavaScript
Język kompilowany - język programowania, który by uzyskać działający program musi zostać wpierw skompilowany do postaci kodu maszynowego (inaczej: do postaci binarnej, w slangu komputerowym binarka). Najpopularniejszymi takimi językami są C++, C, Pascal. Teoretycznie każdy język może być zarówno kompilowany jak i interpretowany, dlatego rozróżnienie opiera się raczej na najpopularniejszych implementacjach niż na cechach samego języka.
Konsolidator (ang. linker) lub program konsolidujący to jeden z programów składowych kompilatora. Konsolidator w trakcie procesu konsolidacji łączy zadane pliki obiektowe i biblioteki statyczne tworząc w ten sposób plik wykonywalny. W systemach uniksowych jest to zazwyczaj program o nazwie ld.
Kompilator – program służący do automatycznego tłumaczenia kodu napisanego w jednym języku (języku źródłowym) na równoważny kod w innym języku (języku wynikowym). Proces ten nazywany jest kompilacją. W informatyce kompilatorem nazywa się najczęściej program do tłumaczenia kodu źródłowego w języku programowania na język maszynowy. Niektóre z nich tłumaczą najpierw do języka asemblera, a ten na język maszynowy jest tłumaczony przez asembler.
Różnica pomiędzy kompilatorem a asemblerem polega na tym, iż każde polecenie języka programowania może zostać rozbite na wiele podpoleceń języka maszynowego (przy czym nowoczesne asemblery również posiadają składnię umożliwiającą zapis wielu poleceń maszynowych jako jednego polecenia kodu źródłowego oraz opcje optymalizacji kodu). Kompilatory mogą posiadać możliwość automatycznej alokacji pamięci dla zmiennych, implementowania struktur kontrolnych lub procedur wejścia-wyjścia.
Stosowanie kompilatorów ułatwia programowanie (programista nie musi znać języka maszynowego) i pozwala na większą przenośność kodu pomiędzy platformami.
Obliczenia symboliczne – operacje matematyczne wykonywane na wyrażeniach matematycznych.
Ogólnie obliczenia możemy wykonywać na liczbach i na symbolach. Wykonując obliczenia na liczbach mamy do czynienia z obliczeniami numerycznymi.
Przykłady obliczeń symbolicznych
uproszczenie równania x3 + 4•x - 6•x daje wynik x3 - 2•x
obliczenie całki nieoznaczonej ∫ x dx – wynikiem jest x2/2 + C
Metody numeryczne – metody rozwiązywania problemów matematycznych za pomocą operacji na liczbach. Otrzymywane tą drogą wyniki są na ogół przybliżone, jednak dokładność obliczeń może być z góry określona i dobiera się ją zależnie od potrzeb.
Metody numeryczne wykorzystywane są wówczas gdy badany problem nie ma w ogóle rozwiązania analitycznego (danego wzorami), lub korzystanie z takich rozwiązań jest uciążliwe ze względu na ich złożoność.
Deklaracje w kodzie źródłowym, zwykle musi poprzedzać pierwsze użycie danego identyfikatora w definiowanym algorytmie. Deklaracja stanowi więc informację dla translatora, która nie generuje kodu wykonywalnego (lecz często powoduje rezerwację pamięci).
Składnia większości języków programowania narzuca umieszczanie deklaracji w określonym miejscu kodu źródłowego. Jest to albo specjalna sekcja programu (modułu, podprogramu, pakietu), albo początek określonego bloku (czyli wszystkie deklaracje muszą zostać umieszczone w tekście programu przed pierwszą instrukcją danego bloku).
Zacznijmy od zmiennych lokalnych.
Podstawową formą deklarowania jest użycie słowa kluczowego “Dim” przed nazwą zmiennej deklarowanej bezpośrednio w procedurze lub funkcji:
Sub p1() |
---|
Dim zmienna1 as Integer |
zmienna1 = 1 |
MsgBox zmienna1 |
End Sub |
Taka deklaracja wskazuje na to, że zostanie utworzona pamięć o nazwie “zmienna1″ będzie przechowywać dane typu “Integer”.
Próba przypisania danych innego typu spowoduje błąd typu, np.
Sub p2() |
---|
Dim zmienna1 as Integer |
zmienna1 = "a" |
MsgBox zmienna1 |
End Sub |
Debug
W przedstawionym wyżej przykładzie błędnym jest próba przypisania litery “a” do zmiennej typu “Integer”. Litera ”a” nie jest przecież liczbą całkowitą.
W języku VBA nie ma trzeba używać destruktora, czyli wystarczy, że coś zadeklarujemy i możemy liczyć na to, że po zakończeniu działania makro automatycznie usunie zmienną z pamięci jednocześnie zwalniając zasoby komputera.
Sposób deklarowania zmiennej z użyciem słowa “Dim” powoduje, że zadeklarowana zmienna jest widoczna lokalnie w danej procedurze / funkcji, gdzie zmienna została zadeklarowana. Czyli nic nie stoi na przeszkodzie, aby inne makra posiadały zmienną o tej samej nazwie, nawet innego typu.
Klucze (ciągi znaków) wykorzystywane do szyfrowania i rozszyfrowania danych. Klucz publiczny jest znany wszystkim, natomiast klucz prywatny znany jest tylko jego właścicielowi. Gdy osoba A chce wysłać poufną wiadomość do osoby B, szyfruje ją, używając klucza publicznego osoby B (ponieważ klucze publiczne są ogólnie znane, nie ma z tym żadnego problemu). Następnie osoba B używa swojego klucza prywatnego, aby tę wiadomość odszyfrować. W tej metodzie wykorzystywany jest klucz publiczny i klucz prywatny tej samej osoby zarówno do szyfrowania, jak i rozszyfrowania. Znając klucz publiczny osoby B, wciąż nic nie wiemy o jej kluczu prywatnym. Jedną z metod, która wykorzystuje technologię klucza prywatnego i publicznego, jest PGP.
Istota kluczy publicznych i prywatnych oparta jest na szyfrowaniu asymetrycznym. Staje się ono coraz
popularniejszym i bardzo bezpiecznym sposobem przesyłania poufnych informacji. Największą zaletą tej
metody szyfrowania jest to, że klucz kodujący pliki, tekst, itp., jest powszechnie znany i dostępny. Taki klucz
nazywa się kluczem publicznym. Dzięki niemu unika się przesyłania tajnych haseł niepewnymi kanałami.
Aby wysłać zaszyfrowany tekst, plik lub załącznik listu do odbiorcy, należy posiadać jego klucz publiczny
oraz, oczywiście, odpowiedni program za pomocą którego będzie można szyfrować, deszyfrować i zarządzać
własnymi zbiorami kluczy. Odbiorca zaszyfrowanej jego kluczem publicznym informacji, odszyfruje ją tylko za
pomocą swojego klucza prywatnego (który jest tajny i powinien być dobrze zabezpieczony - „schowany”).
Klucz publiczny i klucz prywatny tworzą ściśle ze sobą związaną parę kluczy. Tylko klucz prywatny odbiorcy
może odszyfrować informację zakodowaną jego kluczem publicznym. Kluczem publicznym odbiorcy szyfruje
się informacje przeznaczone dla niego. Nie jest możliwe przy jego pomocy odszyfrowanie zakodowanej
informacji, ani poznanie hasła odblokowującego klucz prywatny. Znajomość klucza publicznego nie
pozwala także na poznanie (czyli po prostu na ”odgadnięcie”) klucza prywatnego.
Technologia szyfrowania asymetrycznego z kluczami publicznymi/prywatnymi, umożliwia wprowadzenie
podpisu elektronicznego . Pozwala on na jednoznaczne i nie budzące watpliwości (w sensie autorstwa)
podpisywanie waznych dokumentów, plików, programów, itp.. Klucz prywatny wraz z funkcją haszującą
(funkcjami "hash" są np. SHA-1 i MD5) tworzą podpis elektroniczny dokumentu - pliku, natomiast klucz
publiczny weryfikuje taki podpis, sprawdzając jego prawdziwość. Podpis elektroniczny i narzędzia do
jego weryfikacji, stają się zatem ważnymi elementami strategii uwierzytelniania zasobów danych.
Jak dotąd nie są znane przypadki odszyfrowania informacji zakodowanych współczesnymi (1024-bitowymi
i dłuższymi) kluczami asymetrycznymi przez napastników nie znających odpowiednich kluczy prywatnych.
Świadczy to bardzo dobrze o skuteczności zabezpieczania poufnych informacji przy pomocy tej techniki.
Teoria liczb - dziedzina matematyki, zajmująca się badaniem własności liczb – początkowo tylko naturalnych, i do dziś dla wielu specjalistów są one szczególnie atrakcyjne.
Podstawowe twierdzenie arytmetyki – ważne twierdzenie teorii liczb o rozkładzie liczb naturalnych na czynniki pierwsze.
Treść twierdzenia
Każdą liczbę naturalną większą od 1 można jednoznacznie przedstawić w postaci iloczynu liczb pierwszych.
W szczególności, liczbę pierwszą można przedstawić jako iloczyn zawierający jeden czynnik.
Jednoznaczność rozkładu oznacza, że jeśli liczba n jest przedstawiona jako iloczyn pewnych liczb pierwszych na dwa sposoby, to oba iloczyny zawierają te same czynniki i w tej samej ilości, a różnią się jedynie ich kolejnością.
Sito Eratostenesa - przypisywany Eratostenesowi z Cyreny algorytm wyznaczania liczb pierwszych z zadanego przedziału [2;n]
Ze zbioru liczb naturalnych z przedziału , tj. , wybieramy najmniejszą, czyli 2, i wykreślamy wszystkie jej wielokrotności większe od niej samej, to jest .
Z pozostałych liczb wybieramy najmniejszą niewykreśloną liczbę (3) i usuwamy wszystkie jej wielokrotności większe od niej samej: , przy czym nie przejmujemy się tym, że niektóre liczby (na przykład 6 czy 12) będą skreślane więcej niż raz.
Według tej samej procedury postępujemy dla liczby 5.
Następnie dla 7, 11, 13; aż do sprawdzenia wszystkich niewykreślonych wcześniej liczb.
Wykreślanie powtarzamy do momentu, gdy liczba , której wielokrotność wykreślamy, będzie większa niż .
Dla danej liczby wszystkie niewykreślone liczby mniejsze, bądź równe są liczbami pierwszymi.
Teoria złożoności obliczeniowej – dział teorii obliczeń, którego głównym celem jest określanie ilości zasobów potrzebnych do rozwiązania problemów obliczeniowych. Rozważanymi zasobami są takie wielkości jak czas, pamięć lub liczba procesorów.
Za twórców tej teorii uważani są Juris Hartmanis i Richard Stearns. Jako przykłady problemów t.z.o. można podać problem spełnialności, problem najkrótszej ścieżki, problem faktoryzacji oraz wiele innych, o których wiadomo, że są obliczalne. Kwestią obliczalności zajmuje się teoria obliczalności będąca drugą ważną gałęzią teorii obliczeń.