Jak již bylo dříve uvedeno, naše procedura vůbec nezahrnuje možnost výpočtu komplexně sdružených kořenů. To je samozřejmě pro obecné využití nejen škoda, ale vlastně to prakticky zabraňuje jejímu rozumnému využití. Proto se pokusíme situaci napravit a vytvořit skutečně obecný balíček pro výpočet kořenů kvadratické rovnice. Začneme tedy jednoduchou změnou v souboru kvadrov.ads. Zde se změní pouze parametry deklarované procedury následovně:
package kvadrov is procedure Quadra (A, B, C : in Float; R1, R2, I1, I2 : out Float; Result : out Character); end kvadrov;
Do parametrů byly přidány dva další pro výstup imaginární části kořenů a byl změněn výstupní parametr pro zobrazení typu výsledku. Zásah do souboru s výpočty (kvadrov.adb) už musel být samozřejmě zásadnější:
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions; package body kvadrov is procedure Quadra (A, B, C : in Float; R1, R2, I1, I2 : out Float; Result : out Character) is D, Z : Float; begin D := B**2 - 4.0 * A * C; Z := 2.0 * A; if D < 0.0 then Result := 'K'; R1 := -B / Z; R2 := R1; I1 := Sqrt (-D) / Z; I2 := -Sqrt (-D) / Z; elsif D = 0.0 then Result := 'D'; R1 := -B / Z; R2 := R1; I1 := 0.0; I2 := I1; else Result := 'R'; R1 := (-B + Sqrt (D)) / Z; R2 := (-B - Sqrt (D)) / Z; I1 := 0.0; I2 := I1; end if; end Quadra; begin null; end kvadrov;
Kromě úpravy hlavičky procedury se změnil i samotný výpočet. Není na něm ale nic světoborného, takže upozorníme jenom na přidání nové proměnné Z := 2.0 * A, aby se předešlo zbytečnému provádění výpočtů (celkem se volá šestkrát). Také je možné si všimnout konstrukce rozhodovací logiky:
if podmínka then elsif podmínka then else end if;
Nakonec změníme soubor solve.adb takto:
with Ada.Text_IO; use Ada.Text_IO; with kvadrov; procedure solve is r1,r2,i1,i2 :Float; vysledek : Character; begin kvadrov.Quadra(1.0,3.0,1.0,r1,r2,i1,i2,vysledek); Put_Line("Vysledky reseni: " & vysledek); Put_Line("K1 = " & r1'Img & " " & i1'Img & " i"); Put_Line("K2 = " & r2'Img & " " & i2'Img & " i"); end solve;
V souboru byly opět přidány pouze proměnné pro imaginární část při volání funkce a také jejich zobrazení ve výsledcích. Nové verze souborů jsou v přílohách solve2.adb, kvadrov2.ads a kvadrov2.adb.
Abychom mohli ověřit správnost nejen překladu a spuštění, ale i konečných výsledků, provedeme tři základní výpočty. Každý z nich bude vycházet z jiných vstupních parametrů – koeficientů kvadratické rovnice. Aby to bylo úplně zřejmé, zvolíme sady parametrů tak, aby postupně proběhl výpočet pro všechny tři typy kořenů. Volání procedury tedy proběhne následovně:
kvadrov.Quadra(1.0,3.0,1.0,r1,r2,i1,i2,vysledek); Vysledky reseni: R K1 = -3.81966E-01 0.00000E+00 i K2 = -2.61803E+00 0.00000E+00 i kvadrov.Quadra(1.0,2.0,1.0,r1,r2,i1,i2,vysledek); Vysledky reseni: D K1 = -1.00000E+00 0.00000E+00 i K2 = -1.00000E+00 0.00000E+00 i kvadrov.Quadra(1.0,1.0,1.0,r1,r2,i1,i2,vysledek); Vysledky reseni: K K1 = -5.00000E-01 8.66025E-01 i K2 = -5.00000E-01 -8.66025E-01 i
Jak je vidět, výsledky nám procedura vrací a zdá se, že i správně. Proto se můžeme podívat na další možnosti, které nám Ada nabízí a pomocí kterých můžeme celou aplikaci ještě „doladit“. První změnu provedeme ve dvou krocích, a to pouze v souboru solve.adb:
with Ada.Text_IO; --1 with Ada.Float_Text_IO; --2 with kvadrov; --3 procedure solve is --4 package TIO renames Ada.Text_IO; --5 package FIO renames Ada.Float_Text_IO; --6 package DIO is new Ada.Text_IO.Float_IO(Float); --7 r1,r2,i1,i2 :Float; --8 vysledek : Character; --9 begin --10 kvadrov.Quadra(1.0,3.0,1.0,r1,r2,i1,i2,vysledek); --11 TIO.Put_Line("Vysledky reseni: " & vysledek); --12 TIO.Put_Line("K1 = " & r1'Img & " " & i1'Img & " i"); --13 TIO.Put_Line("K2 = " & r2'Img & " " & i2'Img & " i"); --14 end solve; --15
- v řádku č. 1 zmizel příkaz use, již nebude potřeba
- v řádku č. 2 naopak přibyl odkaz na knihovnu výstupů čísel s desetinnou čárkou. Jenom pro zajímavost zkuste přeložit takto upravený kód a zjistíte, že překladač hlásí chybu. To způsobuje právě odebrání příkazu use na prvním řádku
- Na řádcích 5 až 7 přibyly tři úplně nové a zatím neznámé příkazy. Tyto příkazy ukazují možnosti jak přejmenovat nebo odvozovat stávající standardní nebo uživatelské balíčky a používat je v kódu pod uživatelsky definovaným názvem. V našem případě se jedná o rozlišení dvou výstupních knihoven pro textové a numerické hodnoty. Třetí definice s odvozenou knihovnou je pouze pro ilustraci dané možnosti
- Aby kód fungoval, musíme na řádcích 12 – 14 předřadit knihovnu, ze které se bude následný příkaz volat. Pokud zkusíme překlad nyní, bude vše v pořádku včetně výsledků, ale zatím bez avizované změny formátu
Aby se změna projevila, musíme provést úpravu těchto tří řádků (12 – 14) a změnit jejich kód následovně:
TIO.Put_Line("Vysledky reseni: " & vysledek); --1 TIO.Put("K1 = " ); --2 FIO.Put(Item => r1, Fore => 3, Aft => 6, Exp => 0); --3 TIO.Put(" "); --4 FIO.Put(Item => i1, Fore => 3, Aft => 6, Exp => 0); --5 TIO.Put(" i"); --6 TIO.New_Line; --7 TIO.Put("K2 = " ); --8 DIO.Put(Item => r2, Fore => 3, Aft => 6, Exp => 0); --9 TIO.Put(" "); --10 DIO.Put(Item => i2, Fore => 3, Aft => 6, Exp => 0); --11 TIO.Put(" i"); --12
- 1. řádek se nijak nezměnil
- 2. řádek obsahuje pouze označení kořene a je použit příkaz Put kvůli výstupu na jeden řádek
- 3. řádek obsahuje odkaz na knihovnu pro zobrazení desetinných čísel a jsou v něm také použity 4 nové parametry:
- Item – udává proměnnou, jejíž hodnota se má zobrazit, v tomto případě reálná část kořene
- Fore – počet číslic před desetinou čárkou
- Aft – počet zobrazených desetinných míst
- Exp – zobrazení exponentu. Pokud je jako v našem příkladu hodnota nula, exponent se nezobrazí.
- 4. řádek obsahuje znak mezery mezi reálnou a imaginární částí kořene
- 5. řádek je stejný se třetím, jenom se zobrazuje imaginární část kořene
- 6. řádek obsahuje značku imaginární jednotky
- 7. řádek provádí odřádkování
- 8. – 12. řádek jsou stejné, jenom používají volání odvozené knihovny DIO
Výsledek překladu a spuštění je zde:
Vysledky reseni: R K1 = -0.381966 0.000000 i K2 = -2.618034 0.000000 i
Jak je vidět, formát se změnil a je pro daný příklad mnohem přehlednější, než byl ten původní. Se všemi hodnotami parametrů kromě Item je možné experimentovat a pozorovat jejich vliv na zobrazení výsledků.
V dnešním dílu jsme rozšířili minulý příklad i na komplexní kořeny. V příštím dílu se ještě krátce podíváme na formátování čísel. Také si ukážeme novou vlastnost jazyka Ada – zpracování výjimek. Zaměříme se další vývojové prostředí – Eclipse s příslušným pluginem.