Stacks Image 28

Jednostka programowa

Procedura

Rozpoczniemy od klasycznego przykładu, w którym program drukuje na terminalu napis "Hello, World!"

with Ada.Text_IO;

procedure Hello_World is
begin
Ada.Text_IO.Put_Line ("Hello, World!");
end Hello_World;


Plik: hello_world.adb

Bezargumentowa procedura w języku Ada ma następującą postać:

procedure nazwa is
deklaracje
begin
treść
end nazwa;


Procedura Hello_World nie posiada lokalnych deklaracji, natomiast jej treść składa się z jednej instrukcji, którą jest wywołanie procedury Put_Line znajdującej się w pakiecie Ada.Text_IO.

Aby skompilować plik hello_world.adb należy wykonać polecenie gnatmake:

$ gnatmake hello_world.adb 
gcc -c hello_world.adb
gnatbind -x hello_world.ali
gnatlink hello_world.ali


Wynik uruchomienia skompilowanego programu:

$ ./hello_world 
Hello, World!
$


Prefiks Ada.Text_IO, w wywołaniu Ada.Text_IO.Put_Line, można opuścić jeśli po klauzuli with Ada.Text_IO użyjemy klauzuli use Ada.Text_IO:

with Ada.Text_IO; use Ada.Text_IO;

procedure Hello_World is
begin
Put_Line ("Hello, World!");
end Hello_World;


W drugim przykładzie zaprezentujemy procedurę, która ma parametry w różnych trybach przepływu danych.

Możliwe tryby przepływu danych to:

  • in -- argument jest wyrażeniem, którego wartość zostaje podstawiona w procedurze pod parametr i parametr ten nie może jej zmienić (tryb domyślny)
  • out -- argument jest zmienną, pod którą zostanie podstawiona wartość jaką przyjmie parametr (parametr musi zawsze być przynajmniej raz podstawiony)
  • in out -- argument jest zmienną, której wartość zostaje podstawiona w procedurze pod parametr i parametr może ją zmieniać, przy czym zmieniona wartość będzie widoczna w miejscu wywołania (zmieni się wartość zmiennej będącej argumentem)
 
W poniższym przykładzie zdefiniowano procedurę Step_By_Step, która oblicza sumę odwrotności kwadratów liczb od 1 do 10000 na trzy różne sposoby:

  1. algorytmem Kahana
  2. dodając liczby w kolejności od największej do najmniejszej
  3. dodając liczby w kolejności od najmniejszej do największej

Dodawanie kolejnych liczb w algorytmie Kahana zaimplementowano w postaci procedury Kahan_Sum, która posiada trzy parametry:

  • Value -- dodawana wartość typu rzeczywistego, dostarczana w trybie in;
  • Sum -- częściowa suma dotychczas dodanych wartości, dostarczana w trybie in out;
  • Comp -- kompensacja błędów numerycznych, dostarczana w trybie in out (patrz opis algorytmu: Kahan summation algorithm)

W pliku może znajdować się tylko jedna procedura, zatem definicję procedury Kahan_Sum umieścimy wewnątrz głównej procedury Step_By_Step w miejscu jej lokalnych deklaracji:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure Step_By_Step is

procedure Kahan_Sum (Value : in Float;
Sum : in out Float;
Comp : in out Float) is
Y : Float := Value - Comp;
T : Float := Sum + Y;
begin
Comp := (T - Sum) - Y;
Sum := T;
end Kahan_Sum;

Sum : Float;
Comp : Float;

begin

Sum := 0.0;
Comp := 0.0;
for I in 1 .. 10000 loop
Kahan_Sum (1.0 / Float (I * I), Sum, Comp);
end loop;
Put (" Kahan = ");
Put (Sum, 1, 10, 0);
New_Line;

Sum := 0.0;
for I in 1 .. 10000 loop
Sum := Sum + 1.0 / Float (I * I);
end loop;
Put ("Forward = ");
Put (Sum, 1, 10, 0);
New_Line;

Sum := 0.0;
for I in reverse 1 .. 10000 loop
Sum := Sum + 1.0 / Float (I * I);
end loop;
Put ("Reverse = ");
Put (Sum, 1, 10, 0);
New_Line;

end Step_By_Step;


Plik: step_by_step.adb

Procedura z parametrami ma w języku Ada następującą postać:

procedure nazwa ( parametry ) is
deklaracje
begin
treść
end nazwa;


W treści procedury Step_By_Step użyto instrukcję pętli for. Do drukowania wartości typu rzeczywistego Float użyto procedurę Put z pakietu Ada.Float_Text_IO. Zwróć uwagę na dostępne w języka Ada przeciążenie. Procedura Put użyta jest do drukowania zarówno liczb jak i łańcuchów znaków. Wybór między procedurą Put z pakietu Ada.Text_IO a procedurą Put z pakietu Ada.Float_Text_IO zostaje podjęty przez kompilator na podstawie typu argumentu.

Trzema dodatkowymi argumentami w wywołaniu procedury Put dla liczb rzeczywistych są kolejno:

  • szerokość pola przeznaczonego na drukowanie cyfr przed przecinkiem,
  • szerokość pola przeznaczonego na drukowanie cyfr po przecinku,
  • wartość zero wskazująca na pominięcie części wykładniczej.

Kompilacja przykładu:

$ gnatmake step_by_step.adb 
gcc -c step_by_step.adb
gnatbind -x step_by_step.ali
gnatlink step_by_step.ali


Wynik uruchomienia (kolorem niebieskim zaznaczono cyfry dokładnego wyniku):

$ ./step_by_step 
Kahan = 1.6448340416
Forward = 1.6447253227
Reverse = 1.6448340416
$


Powyższe wartości można porównać z sumą obliczoną w serwisie wolframalpha.com:
Stacks Image 26
null ← → funkcja