|
ELEKTRONINĖS KNYGOS |
|
|
Gintautas GRIGAS
PROGRAMAVIMAS PASKALIU
|
3. LOGINIAI DUOMENYS IR JŲ VALDOMI VEIKSMAI
|
Logika yra programavimo pagrindas. Sąsaja tarp
matematikos ir programavimo prasideda nuo matematinės logikos.
Loginiai duomenys valdo programoje užrašytų
veiksmų atlikimo tvarką.
Sakiniai, kurių atlikimo tvarką reikia
valdyti (pasirinkti vieną iš kelių sakinių, kartoti) jungiami į
struktūrinius sakinius, dar vadinamus valdymo struktūromis. Šiame
skyriuje pateiksime pilną valdymo struktūrų rinkinį, t.y., tokį,
kurio pakanka, bet kurio sudėtingumo veiksmų atlikimo tvarkai išreikšti.
|
3.1. Loginiai duomenys
|
Loginiai duomenys turi tik dvi reikšmes,
kurios Paskalio kalboje žymimos vardais true ir false.
Tai reikšmės teiginio, apie kurį galima pasakyti, kad jis yra
teisingas arba klaidingas. Jeigu teiginys teisingas, tai sakoma, kad
jo loginė reikšmė yra true, jei klaidingas false.
Pavyzdžiui, teiginio Dabar lyja reikšmė yra true,
jeigu dabar iš tikrųjų lyja ir false priešingu
atveju. Teiginys skaičius 24 yra lyginis yra visada
teisingas, nes skaičius 24 iš tikrųjų lyginis. Taigi, šio
teiginio reikšmė yra true.
Teiginius kartais patogu vadinti sąlygomis.
Sakoma, kad sąlyga gali būti tenkinama (jos loginė reikšmė yra true)
arba netenkinama (false). Sąlygos, išreikštos nelygybe
5>3, reikšmė yra visada true, nes skaičius 5 didesnis už
skaičių 3. Sąlygos 5=3 reikšmė yra false, nes skaičiai
3 ir 5 nelygūs. O kokia bus sąlygos a>5 reikšmė, iš anksto
pasakyti negalima, nes ji priklauso nuo kintamojo a reikšmės.
Loginiai duomenys gali būti loginių uždavinių
pradiniai ir galutiniai duomenys. Tokius uždavinius tenka retai
programuoti. Tačiau su loginiais duomenimis susiduriame kiekvienoje
programoje, kai reikia valdyti atliekamų veiksmų eilės tvarką. Dėl
to juos ir nagrinėjame šio skyriaus pradžioje.
Loginiai kintamieji, kaip ir kitų tipų
kintamieji, žymimi vardais. Kad būtų galima juos atskirti nuo kitų
tipų kintamųjų, aprašuose jie apibūdinami žodžiu boolean,
pavyzdžiui,
-
var a, b, log: boolean;
Šiuo aprašu pasakoma, kad kintamieji, pažymėti
vardais a, b ir log, yra loginiai.
Loginiams kintamiesiems galima priskirti tik
logines (loginių reiškinių) reikšmes. Loginės reikšmės
tai loginės konstantos false ir true. Todėl
prieskyros sakiniai
-
a := true;
b := false;
log := a
yra teisingi, nes kintamieji a, b ir log yra
loginio tipo. Tuo tarpu sakiniai:
-
a := 15;
b := 54.12
yra neteisingi, nes loginio tipo kintamieji
negali įgyti skaitinių reikšmių.
Su loginiais duomenimis atliekamos logines
operacijas:
-
not inversija (ne),
and konjunkcija (ir),
or disjunkcija (arba).
Visos loginės operacijos Paskalyje žymimos
baziniais žodžiais, kurie angliškai reiškia tą, ką rašėme
skliaustuose (ne, ir, arba).
Panagrinėkime kiekvieną operaciją.
Inversija (not). Operando reikšmė paneigiama,
t.y. jo loginė reikšmė pakeičiama priešinga:
-
not false = true,
not true = false.
Pavyzdžiui, vietoj
-
a <> b
galima rašyti
not(a = b)
-
arba vietoj
a <= b
galima rašyti
not(a > b).
Inversija yra vienvietė operacija, t.y., ji
taikoma vienam operandui vienai loginei reikšmei. Šiuo požiūriu
ji panaši į minusą, kuriuo užrašyta vienvietė atimtis
aritmetiniame reiškinyje:
-
-x
not a
Ir vienos, ir kitos operacijos ženklas rašomas
prieš operandą. Minusas keičia skaičiaus ženklą priešingu, o
inversija loginę reikšmę priešinga.
Konjunkcijos (and) reikšmė yra lygi true
tiktai tuo atveju, kai abiejų operandų reikšmės yra true. Visais
kitais atvejais konjunkcijos reikšmę yra false:
-
false and false = false,
false and true = false,
true and false = false,
true and true = true.
Konjunkcijos rezultatus galima pavaizduoti
lentele.
a |
b |
a and b |
false |
false |
false |
false |
true |
false |
true |
false |
false |
true |
true |
true |
Disjunkcijos (or) reikšmė yra lygi true, jei
bent vieno operando reikšmė yra true. Kitaip sakant, disjunkcijos
reikšmė yra true, jei pirmojo arba antrojo operando reikšmė
yra true (dėl to disjunkcija kartais vadinama operacija arba):
-
false or false = false,
false or true = true,
true or false = true,
true or true = true.
Disjunkcijos rezultatus galima pavaizduoti
lentele.
a |
b |
a or b |
false |
false |
false |
false |
true |
true |
true |
false |
true |
true |
true |
true |
Loginiai reiškiniai, panašiai kaip ir
aritmetiniai, gali būti ir sudėtingesni, pavyzdžiui,
-
a and b and c,
a or b or c.
Loginių operacijų atlikimo tvarką nurodo
skliaustai. O jeigu skliaustų nėra, tai operacijos atliekamos šia
prioritetų eile:
-
not
and
or
T.y., pirmiausiai atliekamas neigimas, po to
konjunkcija ir paskiausiai disjunkcija.
Vienodo prioriteto operacijos atliekamos iš
kairės į dešinę. Pavyzdžiui, reiškinio
-
a or b or c or d and d
and f
reikšmė skaičiuojama taip, lyg būtų šitaip
surašyti skliaustai:
-
((a or b) or c) or ((d and e)
and f).
Loginę (loginio reiškinio) reikšmę galima
rašyti (parodyti ekrane), priskirti loginio tipo kintamajam,
panaudoti valdymo struktūrose (žr. tolesnius skyrelius).
Programoje loginės reikšmės dažniausiai
atsiranda kaip skaičių (aritmetinių reiškinių) lyginimo
rezultatas. Vartojamos 6 lyginimo operacijos, kurios Paskalio
kalboje žymimos šitaip:
< mažiau,
<= mažiau arba lygu,
= lygu,
<> nelygu,
> daugiau,
>= daugiau arba lygu.
Pateiksime lyginimo operacijų ir jų rezultatų
pavyzdžių.
-
5 < 6
true
5 > 6
false
5 > 5
false
5 >= 5 true
5-1 < 5 true
a-b = (c-d)-r reikšmė priklausys nuo kintamųjų
reikšmių
5.31 < 5.32 true
5.31 < 5 true
Lyginimo operacijų, panašiai kaip ir
aritmetinių, operandai gali būti skirtingo tipo skaičiai
(aritmetiniai reiškiniai). Tokiu atveju sveikasis skaičius pakeičiamas
realiuoju ir lyginami du realieji skaičiai.
Loginių operacijų operandai dažnai būna
lyginimo operacijų rezultatai. Jei nėra skliaustų, Paskalyje
lyginimo operacijos atliekamos paskiausiai. Todėl lyginimo reiškinius,
kai su jais atliekamos loginės operacijos, reikia suskliausti.
Pavyzdžiui, reiškinyje
-
(x > 5) and (x < 10)
skliaustai reikalingi. Jei jų nebūtų, tai
apskaičiuojant reiškinį
-
x > 5 and x < 10
pagal Paskalyje priimtus operacijų prioritetus
pirmiausiai reikėtų atlikti loginę operaciją
-
5 and x
O tai neatitinka mūsų užmanymo. Be to
pirmasis konjunkcijos operandas yra neleistino tipo (todėl šią
klaidą aptiktų kompiliatorius).
Kelias paprastesnes sąlygas loginėmis
operacijomis galima sujungti į vieną sudėtingesnę. Pavyzdžiui,
dviguba nelygybe a<x<b matematikoje nurodomi skaičiaus x reikšmės
rėžiai. Programavime toks užrašas neleistinas. Mat išeitų, kad
pirmosios lyginimo operacijos a<x rezultatas, kuris yra loginė
reikšmė, vėliau lyginamas su skaičiumi b, o skaičiai ir loginės
reikšmės yra nepalyginami duomenys. Dvigubą nelygybę
programavime galima pakeisti dviejų viengubų nelygybių
konjunkcija:
-
(a < x) and (x < b)
Sąlyga tenkinama, t.y., čia parašyto reiškinio
reikšmė yra true, tik tuo atveju, jeigu tenkinamos abi sąlygos,
sujungtos konjunkcijos operacija: ir pirmoji, ir antroji. Dėl to
konjunkcija kartais vadinama operacija ir.
Lyginti galima ne tik aritmetinius reiškinius
(skaičius), bet ir visų kitų paprastųjų tipų duomenis (apie
juos kalbėsime vėliau), tarp jų ir loginius duomenis.
Laikoma, kad reikšmė false yra mažesnė už true, t.y. tenkinama
sąlyga false < true.
Pateiksime programų ar jų fragmentų pavyzdžių.
1 pavyzdys. Miestus A ir B jungia keliai, pažymėti
linijomis (14 pav.). Keliai eina per penkis tiltus, pažymėtus
loginiais kintamaisiais a, b, c, d ir e. Jeigu tiltu galima važiuoti,
tai jį žyminčio kintamojo reikšmė yra true, jeigu ne (pavyzdžiui,
tiltas remontuojamas), tai false.
-
-
14 pav. Tiltai
Loginiam kintamajam kelias priskiriama reikšmė
true jeigu miestus A ir B jungia bent vienas kelias, einantis per
veikiančius tiltus:
-
kelias := ((a or b) and d) or
c and e
2 pavyzdys. Programa, nustatanti, ar
metai olimpiniai.
Pirmosios vasaros olimpinės žaidynės įvyko
1896 m. Atėnuose. Po to jos vyko arba turėjo vykti kas ketveri
metai: 1900 m. antrosios, 1904 m. 3-iosios ir t.t. Neįvykusioms
žaidynėms taip pat buvo skiriamas eilės numeris, o jų metai vis
tiek laikomi olimpiniais.
Pradinis duomuo skaičius, reiškiantis
metus. Rezultatas loginė reikšmė true, jeigu metai
olimpiniai, arba false, jeigu metai neolimpiniai.
-
program olimpiada;
var metai: integer;
olimp:
boolean;
{ ar metai olimpiniai }
begin
read(metai);
olimp := (metai >= 1896) and (metai mod 4 = 0);
writeln(olimp)
end.
Jeigu kompiuteriui pateiksime pradinį duomenį
1999, tai jis ekrane parodys rezultatą
-
FALSE
nes 1999-ieji metai neolimpiniai.
Jei kompiuteriui pateiksime skaičių 2000, tai
ekrane pamatysime žodį
-
TRUE
Aiškiau būtų, jeigu ekrane išvystume
informatyvesnį pranešimą, pavyzdžiui,
-
OLIMPINIAI arba NEOLIMPINIAI
Apie tokių (alternatyvių) pranešimų
formavimą kalbėsime 3.3 skyrelyje.
Pateiktas pavyzdys iliustruoja, kaip į ekraną
rašomos loginės reikšmės. Tačiau nei Paskalio standartas, nei
Turbo Paskalis nenumato loginių reikšmių skaitymo. Mat loginės
reikšmės neturi visuotinai priimtų žymenų, kaip, pavyzdžiui,
skaičiai. Paskalio programų tekstuose vartojami loginių reikšmių
vardai true ir false gali pasirodyti per ilgi tiems kas ruošia
pradinius duomenis. Todėl ten jie dažnai žymimi trumpiau (T ir F
arba 0 ir 1). Tokiais atvejais rašoma loginių duomenų skaitymo
programa, pritaikyta konkrečiam loginių reikšmių žymėjimui.
Uždaviniai
3.1.1. Duotas kintamųjų aprašas:
-
var a, b, c: integer;
x, y, z: boolean;
-
Kurie iš šių sakinių yra neteisingi ir
kodėl?
-
a) x := true;
b) a := x;
c) x := a;
d) x := a - b;
e) x := c = y;
f) x := y + a;
g) c := y + 2;
h) a := b = c;
i) c := a + b.
3.1.2. Ką parašys kompiuteris pagal šitokią
programą?
-
program logika;
var a, b: integer;
aa, bb, cc: boolean;
begin
a := 3; b := 5;
aa := a < b;
bb := a > b;
cc := aa;
writeln(aa);
writeln(aa);
writeln(aa)
end.
3.1.3. Sakėme, kad dviguba nelygybė
a<x<b su aritmetiniais duomenimis neleistina. O ar ji
leistina su kurio
nors kito tipo duomenimis?
3.1.4. Parašykite šešių loginių reikšmių
lyginimo operacijų <, <=, = , <>, >, >= rezultatų
lenteles (analogiškas
konjunkcijos ir disjunkcijos lentelėms).
3.1.5. Kintamųjų reikšmės yra tokios: a =
10, b = 20, log = true, lg = false. Kokios šių
loginių reiškinių
reikšmės:
-
a) log or lg;
b) log and lg;
c) (a = 10) and (b = 20);
d) (a <> 10) or (b = 20);
e) (a > 5) and (b > 5) and (a < 20) and
(b < 30);
f) (a > 5) and (b > 5) and (a < 10) and
(b < 30);
g) (a > 5) and (b > 5) or (a < 10) and
(b < 30);
h) (not (a < 15) or (not (b < 30));
i) not (a = b);
k) not (not (a = b));
l) not (not (not (a = b)))?
3.1.6. Pradiniai duomenys trys skaičiai a,
b ir c. Parašykite loginį reiškinį, kurio reikšmė
būtų true,
tada it tiktai tada, kai:
-
a) visų trijų kintamųjų a, b ir c reikšmės
lygios;
b) visų trijų kintamųjų a, b ir c reikšmės skirtingos;
c) kurių nors dviejų kintamųjų reikšmės lygios;
d) visų trijų kintamųjų a, b ir c reikšmės yra lyginiai
skaičiai;
e) visų trijų kintamųjų reikšmės yra teigiamos, bet ne
didesnės kaip 100.
3.1.7. Pradiniai duomenys keturi skaičiai
a, b, c ir d. Parašykite loginį reiškinį, kurio
reikšmė būtų true,
tada it tiktai tada, kai:
-
a) visų keturių kintamųjų a, b, c ir d
reikšmės išdėstytos didėjančiai, t.y.,
a < b < c < d
-
b) visų keturių kintamųjų a, b, c ir d
reikšmės išdėstytos nemažėjančiai, t.y.,
a <= b <= c <= d
3.1.8. Parašykite loginį reiškinį, kurio
reikšmė būtų true, jeigu iš trijų atkarpų. kurių ilgiai
duoti (yra kintamųjų
a, b, ir c reikšmės), galima surinkti:
-
a) trikampį,
b) lygiašonį trikampį,
c) lygiakraštį trikampį.
3.1.9. Apskritimo centro koordinatės yra cx ir
cy ir spindulys r. Taško koordinatės yra tx ir
ty. Parašykite
loginį reiškinį, kurio reikšmė būtų true, jeigu taškas
yra apskritimo
viduje.
3.1.10. Elektros lemputė, pažymėta X,
jungiama į tinklą per 15 paveiksle parodytą keturių
jungiklių schemą. Jungiklių būsenos pažymėtos loginiais
kintamaisiais a, b, c ir d.
Jeigu
jungiklis įjungtas (per jį teka elektros srovė), tai jį
atitinkančio kintamojo
reikšmė
yra true, jei išjungtas (srovė neteka) false.
Parašykite loginį reiškinį, kurio
reikšmė
būtų true, jeigu:
-
a)
lemputė šviečia;
b) yra trumpas jungimas schemoje;
c) lemputė nešviečia, t.y., per schemą srovė neteka.
15 pav.
3.1.11. Ankstesnio uždavinio schemoje lemputė
pakeista laidu (16 pav.). Parašykite loginį
reiškinį,
kurio reikšmė būtų true, jeigu grandine (tarp taškų A
ir B) teka elektros
srovė.
16
pav.
3.1.12. Parašykite loginį reiškinį, kurio
reikšmė būtų true, jeigu metai m keliamieji.
-
Ar metai keliamieji, nustatoma pagal tokias
taisykles: 1) jeigu metai nėra šimtmečio metai, tai jie yra
keliamieji, jeigu dalosi iš 4; 2) jeigu metai yra šimtmečio
metai, tai jie yra keliamieji, jeigu šimtų skaičius dalosi iš
4 (pvz., 2000 metai yra keliamieji, o 2100 metai ne
keliamieji).
3.1.13. Turime sveikųjų skaičių tipo kintamąjį
a ir šitokius loginius reiškinius:
-
a+1 > a
a+1 > 1
a*5 > 0
a*a > 0
a*a >= 0
-
Ties reiškiniu parašykite:
žodį true, jeigu jo reikšmė yra visada true;
žodį false, jeigu jo reikšmė yra visada false;
žodžius true false, jeigu gali būti vienaip ir kitaip
Praktikos darbas
3.1.1. Stačiakampis. Parašykite programą,
kuri parodytų ekrane žodį TRUE, jeigu taškas yra viduje stačiakampio,
kurio kraštinės lygiagrečios koordinačių ašims. Pradinius
duomenis parinkite patys ir tokius, kad jų būtų kuo mažiau
(pakanka 6 skaičių trijų taškų koordinačių).
Parinkite keletą pradinių duomenų rinkinių,
tokių, kad jais būtų galima visapusiškai patikrinti programą.
Keletas taško padėčių stačiakampio atžvilgiu parodyta 17
paveiksle.
17
pav.
Taškui apibūdinti reikia dviejų koordinačių
(tx ir ty). Stačiakampiui apibūdinti pakanka dviejų kurių nors
priešingų jo kampų koordinačių (ax, cx, ay, cy).
|
3.2. Loginių reiškinių pertvarkymas
|
Pirmą kartą skaitant knygą šį skyrelį
galima praleisti. Prie jo bus naudinga grįžti, kai pajusite, kad
loginius reiškinius rašote per ilgus ir negražius ir norėsite
juos suprastinti.
Programavime susiduriame bent su dviejų rūšių
reiškiniais: aritmetiniais ir loginiais. Aritmetiniuose reiškiniuose
vartojame aritmetines operacijas. Šių operacijų savybes gerai žinome.
Jas išmokstame mokykloje. Jomis remdamiesi pertvarkome aritmetinius
reiškinius sutraukiame panašius narius, iškeliame bendrą
dauginamąjį prieš skliaustus ir pan.
Panašios taisyklės taikomos ir loginiams reiškiniams.
Tiktai loginių operacijų savybės šiek tiek skiriasi nuo
aritmetinių. Todėl ir loginių reiškinių pertvarkymo taisyklės
šiek tiek skiriasi (nors yra ir tokių pat) nuo aritmetinių reiškinių
pertvarkymo taisyklių. Pateiksime svarbesnes.
1. Sukeitus vietomis konjunkcijos arba
disjunkcijos operandus, rezultatas nepasikeičia:
-
a and b = b and a,
a or b = b or a.
2. Vienodos operacijos atliekamos bet kuria
tvarka (vadinasi, jų operandus galime grupuoti kaip norime):
-
a and (b and c) = (a and
b) and c,
a or (b or c) = (a or b) or c.
3. Vienodus operandus galima iškelti už
skliaustų:
-
(a and b) or (a and c)
= a and (b or c),
(a or b) and (a or c) = a or (b and
c).
Pirmosios dvi taisyklės atitinka sudėties ir
daugybos dėsnius. Aritmetiniuose reiškiniuose prieš skliaustus
galima įkelti tik bendrus dauginamuosius, o logikoje bet kurios
operacijos (konjunkcijos arba disjunkcijos) operandų. Apskritai,
kiekviena logikos taisyklė, taikoma konjunkcijai, tinka ir
disjunkcijai (ir atvirkščiai). Tačiau, taikant taisyklę kitai
operacijai, reikia tapatybėje (formulėje) visas operacijas ir
visas konstantas pakeisti priešingomis (and => or,
or => and, false => true, true
=> false) ir galbūt pakeisti
skliaustų išdėstymą taip, kad išliktų ankstesnė operacijų
atlikimo tvarka. Šis operacijų keitimo principas vadinamas dualumo
principu. Jis labai praverčia besimokančiam pakanka žinoti
vieną taisyklę, o jos antrininkę galima gauti taikant
dualumo principą.
4. Jei operandai sutampa, tai rezultatas lygus
operandui:
-
a and a = a,
a or a = a.
5. Jei vienas operandas konstanta, tai
rezultatas lygus vienam iš operandų:
-
a and true = a,
a or false = a,
a and false = false,
a or true = true.
6. Konjunkciją galima pakeisti disjunkcija (ir
atvirkščiai) įkeliant į skliaustus (iškeliant iš jų) inversiją:
-
not (a and b) = not a or
not b,
not (a or b) = not a and not b.
7. Operando ir jo inversijos konjunkcijos
(disjunkcijos) rezultatas yra konstanta:
-
a and not a = false,
a or not a = true.
8. Dvi iš eilės einančios inversijos
panaikina viena kitą:
-
not not a = a.
1 pavyzdys. Suprastinsime loginį reiškinį
-
a and not b
-
Pritaikę 6 taisyklę gauname:
not a or not not b.
-
Antrajam operandui pritaikę 8 taisyklę,
gauname:
not a or b.
Daug kartų pertvarkydami ilgą reiškinį,
galime suklysti. Norėdami įsitikinti, ar nepadarėme klaidų,
vietoj kintamųjų įrašykime į reiškinius konkrečias reikšmes
ir apskaičiuokime tų reiškinių reikšmes. Jei reiškinį
pertvarkėme teisingai, tai jo reikšmės prieš pertvarkymą ir po
jo sutampa esant bet kokioms kintamųjų reikšmėms. Kadangi
loginis kintamasis gali įgyti tik dvi reikšmes, tai reiškinį,
kuriame yra n kintamųjų, reikės tikrinti 2n kartų.
2 pavyzdys. Tarkime, kad pertvarkę reiškinį
-
(a or b) and (a or not
b) or b
-
gavome paprastesnį reiškinį:
a or b.
Patikrinkime, ar pertvarkydami nepadarėme
klaidų, t.y. ar šių dviejų reiškinių reikšmės sutampa, esant
bet kokioms jų kintamųjų a ir b reikšmėms:
a |
b |
(a or b) and (a or not
b) or b |
a or b |
false |
false |
false |
false |
false |
true |
true |
true |
true |
false |
true |
true |
true |
true |
true |
true |
Kaip matome, visais atvejais pradinio ir
pertvarkyto reiškinio reikšmės sutampa. Vadinasi, pradinis reiškinys
buvo pertvarkytas teisingai.
Uždaviniai
3.2.1. Suprastinkite šiuos reiškinius:
-
a) not (a or b) and not
(a and b)
b) a and b or not a or not (b or not
a)
3.2.2. Ankstesnio skyrelio 3.2.10 uždavinio
atsakyme pateikti šitokie loginiai reiškiniai:
-
a) a and not b and c and
not d or not a and b and not c and
d
b) a and b or c and d
c) not a and not b and not c and not
d or not a and not d or not b or not
d
Pabandykite juos suprastinti.
|
3.3. Vienas iš dviejų veiksmų
|
Gyvenime dažnai atsiduriame kryžkelėse, kai
reikia pasirinkti, kuriuo keliu eiti. Tada žmogus sustoja, svarsto,
pagaliau pasirenka.
Pasirinkimas įprasta situacija
programavime. Tiktai kompiuteris nesustoja ir nesvarsto visi
galimi keliai turi būti iš anksto numatyti ir į programą surašytos
vienareikšmės jų parinkimo sąlygos.
Kompiuterio prigimtis dvejetainė. Todėl dažniausiai
pasirenkamas vienas kelias iš dviejų. Vieno veiksmo iš dviejų
parinkimas nurodomas sąlyginiu sakiniu, kurio pavidalas šitoks:
-
if loginis reiškinys then sakinys1
else sakinys2
Po žodžio if einantis loginis reiškinys
dar vadinamas sąlyga.
Atliekamas tik vienas iš dviejų sakinių:
-
sakinys, einantis po žodžio then
(sakinys1), jeigu loginio reiškinio reikšmė yra true
(sąlyga tenkinama) arba
-
sakinys, einantis po žodžio else
(sakinys2), jeigu loginio reiškinio reikšmė yra false
(sąlyga netenkinama). Sakinių pasirinkimas grafiškai
pavaizduotas 18 paveiksle
18
pav. Sąlyginio sakinio schema
1 pavyzdys. Didesniojo skaičiaus
radimas.
-
program didesnysis;
var a, b, max: integer;
begin
read(a, b);
if a >= b then max := a
else max := b;
writeln(max);
end.
Jei pradiniai duomenys būtų skaičiai 5 ir 6,
tai būtų atliekami šie veiksmai:
a
b max
read(a,
b)
5
6
? skaitomi
pradiniai duomenys
a >=
b
5
6
? tikrinama sąlyga
max :=
b
5
6 6
writeln(max)
5
5
6 rašomas
rezultatas
Kad aiškiau matytųsi sąlyginio sakinio šakos,
programoje jas rašome viena po kitos, t.y. žodį else lygiuojame
su jį atitinkančiu pirmosios šakos žodžiu then. Kartais
patogu sąlygai (su žodžiu if) skirti atskirą eilutę (ypač
kai ilgesnė sąlyga), pavyzdžiui,
-
if (alfa*alfa) >= (beta*beta)
then ...
else ...
2 pavyzdys. Programa, nustatanti, ar
skaičius dalus iš 7.
-
program dalus7;
var x: integer;
begin
read(x);
write('Skaičius ', x);
if x mod 7 = 0
then write(' dalus')
else write(' nedalus');
writeln(' iš 7')
end.
Jei kompiuteriui pateiksime skaičių 12345,
tai gausime atsakymą:
Skaičius 12345 nedalus iš 7
3 pavyzdys. Programa olimpinių žaidynių
eilės numeriui nustatyti.
Panašų uždavinį jau sprendėme (žr. 3.1
skyr. 2 pavyzdį). Ten nustatėme, tik patį faktą, ar metai
olimpiniai. Panaudodami sąlyginį sakinį galėsime nustatyti ir žaidinių
eilės numerį. Neįvykusioms žaidynėms skiriamas eilės numeris,
o jų metai vis tiek laikomi olimpiniais.
Pradinis duomuo skaičius, reiškiantis
metus. Rezultatas olimpinių žaidynių numeris, jeigu metai
olimpiniai, arba nulis, jeigu metai neolimpiniai.
-
program olimpiadanr;
var metai,
nr: integer; {
olimpiados eilės numeris }
begin
read(metai);
if (metai >= 1896) and (metai mod
4 = 0)
then nr := (metai - 1896) div 4 + 1
else nr := 0;
writeln(nr)
end.
Sąlyginiame sakinyje (po žodžių then ir
else) gali eiti bet kokie sakiniai, tarp jų ir sąlyginiai.
Tada šakos šakojasi į naujas šakas ir gaunamas medis.
4 pavyzdys. Pradiniai duomenys trys
skaičiai. Programa mažiausiam iš jų rasti.
-
program minimumas;
var a, b, c, min: integer;
begin
read(a, b, c);
if a < b then if a < c then
min := a
else min := c
else if b < c then min := b
else min := c;
writeln(min)
end.
Priklausomai nuo to, ar tenkinama sąlyga a
< b, atliekama viena kuri nors gaubiančiojo sąlyginio sakinio
šaka. Kiekvieną šaką sudaro naujas sąlyginis sakinys, turintis
dvi šakas (19 pav).
19
pav. Veiksmų šakojimasis 3 pavyzdžio sąlyginiame sakinyje
Nebūtinai kiekvienas sąlyginis turi būti
simetriškas viena sąlyga gali šakotis daugiau, kita mažiau.
Lengviau parašyti ir suvokti tokį nesimetrišką
sąlyginį sakinį, kuriame veiksmai šakojasi tik po else. Šitaip
nuo daugelio galimų kelių (galbūt iki galo dar neišnagrinėtų)
atskiriamas vienas, kurio veiksmai jau aiškus ir tie veiksmai užrašomi
po then, o visa kita, kas dar toliau lieka skaldyti į šakas, rašoma
po else.
5 pavyzdys. Užrašysime sakinius
kintamojo y reikšmei, kuri priklauso nuo kintamojo x reikšmės ir
apskaičiuojama pagal šitokią formulę:
-
0,
jei x < -10,
10 + x, jei -10 <= x <= -5,
y = 5, jei -5 < x < 5,
10 x, jei 5 <= x <= 10,
0, jei x
> 10.
Kaip kintamojo y reikšmė priklauso nuo
kintamojo x reikšmės, rodo grafikas (20 pav.).
20 pav.
Sąlyginiu sakiniu ta priklausomybė išreiškiama
taip:
-
if x < -10 then y := 0
else if x <= -5 then y := 10 + x
else if x < 5 then y := 5
else if x <= 10 then y := 10 - x
else y := 0
Veiksmų šakojimasis grafiškai pavaizduotas
21 paveiksle.
21
pav.
Pastebėsime, kad sąlygos, einančios po žodžių
else if, paprastesnė už sąlygas, esančias uždavinio formulėje.
Mat kintamojo x reikšmės rėžį pakanka tikrinti tik iš vienos
pusės iš kitos pusės jis jau buvo patikrintas prieš
patenkant į tą sakinio šaką.
Sąlyginis sakinys, kuriame po žodžių else
įterpiami vis nauji sąlyginiai sakiniai, žodžius else lygiuojant
su juos atitinkančiais then, labai išsitęstų į dešinę.
Programos vaizdumas nenukenčia, jeigu sakinio dalis, prasidedančias
žodžių pora else if, rašome šiek tiek patrauktas į dešinę.
Uždaviniai
3.3.1. Kokios bus kintamųjų a ir b reikšmės,
atlikus šitokią sakinių seką?
-
a := 10; b := 6;
if a > b then a := a - b;
else a := a + 3;
if a > 6 then b := b + 1
else b := b + 2
3.3.2. Atlikus sakinį
-
if a > b then a := a - b
else b := b - a
-
gautos šitokios kintamųjų a ir b reikšmės:
a = 5, b = 5. Kokios galėjo būti šių kintamųjų reikšmės,
prieš atliekant sąlyginį sakinį.
3.3.3. Turime tokią programą mažiausiam
iš trijų skaičių rasti.
-
program minim;
var a, b, c, min: integer;
begin
read (a, b, c);
if (a < b) and (a < c) then min
:= a
else if (b < c) and (b < a) then
min := b
else min := c;
writeln(min)
end.
-
Ar ji teisinga? Jei taip, ar ji visada duos
tokį pat rezultatą, kaip ir programa minimumas (žr. 3
pavyzdį).
3.3.4. Parašykite sąlyginį sakinį rezultato
f reikšmei rasti pagal formulę
-
f = a + b, jei a nelyginis,
a * b, jei a
lyginis.
3.3.5. Duotas sąlyginis sakinys
-
if a < 3
then c := 1
else if a > = 5 then c := 2
else c := 3
-
Kokiai kintamojo a reikšmei esant,
kintamajam c bus priskirta reikšmė 3?
3.3.6. Programą olimpiadanr pakeiskite
taip, kad būtų spausdinamas šitokio pavidalo
tekstas:
-
1999 metai yra neolimpiniai
2000 metai yra olimpiniai
3.3.7. Programoje dalus7 į ekraną rašomo
teksto eilučių pradžiose ir pabaigose yra tarpų.
Kam jie reikalingi?
Kaip atrodytų rašomas į ekraną tekstas, jeigu juos pašalintume?
3.3.8. Parašykite programą, kuri atliktų
tokius veiksmus su pradiniu duomeniu: jeigu jis
teigiamas, tai jį
paverstų tokio pat modulio neigiamu skaičiumi, jeigu neigiamas
paverstų jo
moduliu.
Praktikos darbas
3.3.1. Programos atlikimas pažingsniui. Programą
minimumas (žr. 4 pavyzdį) papildykite dialogo veiksmais ir
išbandykite su kompiuteriu, kai pradiniai duomenys yra šitokie:
-
5
6 10
5 6
2
25 17 18
25 17 16
Stebėkite kokie sakiniai kokiu atveju yra
atliekami. Tam panaudokite pažingsninį kompiliatoriaus režimą.
Tą patį padarykite su programa olimpiadanr
(žr. 3 pavyzdį). Pradinius duomenis programos išbandymui
pasirinkite patys.
|
3.4. Įvairesni šakojimosi atvejai
|
Ne visada visi šakos veiksmai išreiškiami
vienu sakiniu. Būna atvejų, kai reikia rašyti kelis sakinius, o
kartais šaka būna tuščia be jokių veiksmų. Tokius atvejus
ir panagrinėsime.
Tuščias sakinys. Dažnai veiksmą
reikia atlikti tik vienu atveju (pavyzdžiui, kai sąlyga
tenkinama), o priešingu atveju nereikia nieko daryti. Pavyzdžiui,
jeigu reikia kintamojo a reikšmę pakeisti jos moduliu, tai skaičiaus
ženklą reikia keisti tik tada, kai jis neigiamas, o jeigu jis
teigiamas, tai nereikia nieko daryti. Tokius veiksmus galima užrašyti
bet kuriuo iš tokių sąlyginių sakinių:
-
if a < 0 then a := -a
else;
arba
if a >= 0 then
else a := -a
Ten, kur nereikia atlikti veiksmų, nieko ir
nerašome. Tokia tuščia vieta vadinama tuščiu sakiniu. Pirmuoju
atveju tuščias sakinys parašytas po else, antruoju
po then.
Sakiniai skiriami kabliataškiais. jeigu netyčia
tarp gretimų dviejų sakinių parašysime ne vieną, o du (ar
kelis) kabliataškius, tai klaidos nebus bus laikoma, kad tenai,
tarp kabliataškių yra tušti sakiniai.
Sutrumpintas sąlyginis sakinys. Kai tuščias
sakinys yra po else, tai galima praleisti ir žodį else,
pavyzdžiui,
-
if a < 0 then a := -a
Šitokia Paskalio kalbos konstrukcija
sutrumpintu sąlyginiu sakiniu. Jo bendrasis pavidalas yra šitoks:
-
if loginis reiškinys then sakinys
Sutrumpinto sąlyginio sakinio schema pateikta
22 paveiksle.
Vienas į kitą įdėti sutrumpinti sąlyginiai
sakiniai. Tarkime, kad turime šitaip netvarkingai į vieną
eilutę surašytus vienas į kitą įdėtus sakinius:
-
if b1 then if b2 then
S1 else S2
Kuriam sakiniui priklauso šaka else S2:
pirmajam (if b1 then), ar antrajam (if b2 then).
Paklausti galima ir kitaip: kurį then atitinka else,
arba kuris iš šių dviejų vienas į kitą įdėtų sąlyginių
sakinių yra sutrumpintas?
22
pav. Sutrumpinto sąlyginio sakinio schema
Yra susitarta tokį užrašą interpretuoti šitaip:
-
if b1
then if b2
then S1
else S2
T.y., vidiniai sakiniai laikomi (jeigu tik
galima) nesutrumpintais.
Sudėtingesniam sąlyginiam sakiniui
perskaityti galime rekomenduoti paprastą taisyklę trūkstamus
else surašyti sakinio gale. Tuomet nesunkiai ir vienareikšmiškai
atrandami žodžių if, then ir else trejetai.
Vadinasi, sakinį
-
if b1 then if b2 then if b3
then S1 else S2
reikia suprasti šitaip:
-
if b1
then if b2
then if b3 then S1
else S2
else
else
Kai norime parašyti sudėtingesnį sakinį,
galime rekomenduoti pradžioje surašyti visus else, sakinius
taisyklingai sulygiuoti, o po to nereikalingus else išbraukti.
Sudėtinis sakinys. Kalbėdami apie
sakinius, rašomus į bet kurią sąlyginio sakinio šaką,
vartojome vienaskaitą. O ką daryti, kai vienu ar kitu atveju
reikia atlikti ne vieną, o kelis sakinius?
Tada tie keli sakiniai rašomi tarp žodžių begin
ir end. Šitaip sakinių grupė paverčiama vienu sakiniu,
kuris vadinamas sudėtiniu. Jo schema yra tokia:
-
begin
sakinys1;
sakinys2;
...
sakinysn
end
Sudėtinis sakinys tai vienas sakinys, kurį
galima rašyti visur ten, kur ir bet kurį paprastą sakinį.
1 pavyzdys.
-
if a < 0 then begin
b := b + 1; c := c + 1
end
else begin
b := b - 1; c := c - 1
end
Kad būtų geriau matomos sudėtinio sakinio
ribos, žodžiai begin ir end rašomi vienas po kitu
ir vienodai atitraukiami nuo kairiojo eilutės krašto, o jiems
priklausantys sakiniai truputį patraukiami į dešinę. Trumpo sudėtinio
sakinio ribos gerai matomos ir tada, kai visas jis parašytas
vienoje eilutėje, pavyzdžiui,
-
if a < 0
then begin b := b + 1; c := c + 1 end
2 pavyzdys. Pradiniai duomenys du
skaičiai. Rezultatas apskaičiuojamas pagal formulę
-
s = x2 + y3;
čia x didesnysis, o y mažesnysis pradinis duomuo.
Sudarome programą:
-
program p;
var a, b, x, y: integer;
begin
read(a, b);
if a < b
then begin x := b;
y := a
end
else begin x := a;
y := b
end;
writeln(x*x + y*y*y)
end.
Sudėtinį sakinį gali sudaryti daugelis
kitokių sakinių, tarp jų gali būti sąlyginių ir trumpesnių
sudėtinių sakinių.
Kiekvienos programos veiksmų dalį sudaro
sakiniai, parašyti tarp žodžių begin ir end. Taigi
būsime teisūs, jeigu sakysime, kad kiekvienos programos visi
veiksmai išreiškiami vieninteliu sudėtiniu sakiniu.
Skyrybos klaidos. Atkreipiame dėmesį
į tai, kad prieš žodį else kabliataškio rašyti
negalima. Jeigu jį ten padėtume, tai reikštų, kad po kabliataškio
eina jau kitas sakinys (kabliataškis skiria sakinius), pvz.:
-
if b then S1; else S2
Kadangi žodžiu else negali prasidėti
joks sakinys, tai tokią klaidą pastebės Turbo Paskalio
kompiliatorius.
O jeigu sakinyje
-
if b then S
netyčia padėtume kabliataškį po žodžio then:
-
if b then; S
tai programa liktų taisyklinga būtų
laikoma, kad po then yra tuščias sakinys, kabliataškis
atskiria sakinį S nuo sąlyginio. Sakinys S nebepriklauso sąlyginiam
ir atliekamas visada. Tokios klaidos kompiliatorius nerastų, o mes
stebėtumės, kodėl kompiuteris duoda ne tokį rezultatą, kokio
tikimės.
Uždaviniai
3.4.1. Duota programa
-
program mini;
var a, b, c, min: integer;
begin
read(a, b, c);
min := a;
if b < min then min := b;
if c < min then min := c;
write(min)
end.
-
Ar visada kompiuteris išspausdins vienodus
rezultatus, atlikęs programą minim ir minimumas
(žr. 3.3 skyr., 4 pavyzdį), kai pradiniai duomenys tie patys?
3.4.2. Parašykite sąlyginius sakinius, pagal
kuriuos būtų palyginamos kintamųjų a ir b
reikšmės ir,
jeigu jos nelygios:
-
a) iš didesniosios atimama mažesnioji;
b) mažesnioji padidinama vienetu;
c) didesnioji sumažinama vienetu.
3.4.3. Duota programa
-
program skaitymas;
var a, b, c, d: integer;
begin
read(a, b);
if a < b
then read(c, d)
else if a > b
then read(d, c);
write(a, ' ', b, ' ', c, ' ', d)
end.
-
Pradiniai duomenys šitokie:
a) 1 2 3 4
b) 4 3 2 1
-
Ką išspausdins kompiuteris?
-
Nors ir apskaičiavote rezultatą, bet programa
yra neteisinga: gali būti tokių pradinių duomenų, kuriems esant
bus vartojamos neapibrėžtos kintamųjų reikšmės. Kokiems
pradiniams duomenims esant tai atsitiks?
3.4.4. Pavartodami sudėtinius sakinius,
suprastinkite šį programos fragmentą:
-
if a > b then c := 1;
if a > b then d := 2;
if a <= b then c := 3;
if a <= b then d := 4
3.4.5. Duota programa:
-
program pp;
var a, b, xx, yy, s: integer;
begin
read(a, b);
xx := a*a;
yy := b*b;
if a < b then xx := xx*a
else yy := yy*b;
s := xx + yy;
write(s)
end.
-
Ar programa pp atlieka tokius pat veiksmus,
kaip ir 2-ojo pavyzdžio programa p?
3.4.6. Duoti du sudėtiniai sakiniai:
-
a) begin
c := 0;
if a < 5 then c := 1;
if a > 5 then c := 2
end;
-
b) begin
c := 0;
if a < 5 then c := 1
else c := 2
end
-
Ar atlikus šiuos sakinius visada rezultatas
(kintamojo c reikšmė) yra tas pats? Jeigu ne, tai su kuria
kintamojo a reikšme jie skiriasi?
3.4.7. Duota programa:
-
program perdaug;
var a, b: integer;
begin
read(a, b);
if a < 10 then begin a := 10;
b := b - 5
end;
if a < 5 then begin a := 5;
b := b - 5
end;
writeln(a, b: 6)
end.
-
Sutrumpinkite ją, pašalindami vieną
nereikalingą sakinį.
3.4.8. Duota programa:
-
program intervalai;
var a, b, c: integer;
begin
read(a, b, c);
if a < 0 then a := 2 - a;
if b < 0 then b := 10;
if c > 10 then c := 10;
writeln(a, ' ', b, ' ', c)
end.
-
Nustatykite, kokiuose intervaluose bus rezultatų
reikšmės. Intervalus nurodykite nelygybėmis. (Kokie rezultatai
bus išspausdinti, be abejo, priklauso nuo pradinių duomenų. Tačiau
ir nežinant jų, vien iš programos teksto galima šį tą pasakyti
apie rezultatus.)
3.4.9. Taikydami logines operacijas,
suprastinkite šiuos sakinius:
-
a) if a > b then
if b < c then a := a + 1;
-
b) if log then
else
a := a + 1;
3.4.10. Programą dalus (žr. 3.3 skyr. 3
pavyzdį) pakeiskite taip, kad joje būtų tik vienas
suprastintas sąlyginis
sakinys.
Praktikos darbas
3.4.1. Vidurinysis skaičius. Pradiniai
duomenys trys sveikieji skaičiai. Parašykite programą, kuri
rastų vidurinįjį skaičių, jeigu tie skaičiai būtų surikiuoti
eilės tvarka (nemažėjančiai arba nedidėjančiai). Pateikiame
keletą pavyzdžių.
-
Pradiniai duomenys
Rezultatas
33 55
22
33
22 33
22
22
22 33
33
33
55 55
55
55
|
3.5. Lygčių sprendimai su pradinių duomenų
tyrimu
|
Turėdami sąlyginį sakinį galime ištirti
pradinius duomenis. Tai ypač patogu rašyti lygčių sprendimo
programas, kai pirmiausia reikia ištirti kiek ir kokių sprendinių
turi lygtis.
Kvadratinė lygtis
-
ax2 + bx + c = 0.
Šaknys randamos pagal formulę
-
-b ± Vb2 - 4ac
x =
2a
Reiškinys
-
D = b2 - 4a
vadinamas kvadratinės lygties diskriminantu.
Kai D < 0, tai lygtis neturi šaknų, kai D = 0, tai lygtis turi
vieną šaknį, kai D > 0, tai lygtis turi dvi šaknis. Taigi,
programoje reikia pirmiausiai apskaičiuoti determinantą,
nustatyti, kiek lygtis turi šaknų ir rasti jas.
-
program kvlygtis;
const paklaida = 0.00001;
var a, b,
c,
{ lygties koeficientai }
D,
{ diskriminantas }
x1, x2:
real;
{ šaknys }
begin
read(a, b, c);
D := b*b - 4*a;
if abs(d) <= paklaida
then writeln('x = ', -b / (2*a):
10: 2)
else if D > paklaida
then begin
writeln('x1 = ', (-b + D) / (2*a));
writeln('x2 = ', (-b - D) / (2 * a))
end
else writeln('Lygtis sprendinių neturi')
end.
Programoje tikrinama, ar diskriminantas D
nedidesnis už labai mažą dydį paklaida, vietoj
matematikoje įprasto patikrinimo, ar jis lygus nuliui. Mat
matematikoje laikoma, kad visi dydžiai yra absoliučiai tikslūs.
Tuo tarpu kompiuteryje realieji skaičiai vaizduojami apytiksliai. Dėl
paklaidų vietoj nulio gali atsirasti labai mažas skaičius,
artimas nuliui, bet nelygus jam. Taip atsitinka ne visada, bet gera
programa turi nepriekaištingai veikti su visais pradiniais
duomenimis. Dėl to panaudojome konstantą paklaida.
Praktikos darbai
3.5.1. Dviejų tiesinių lygčių sistema
-
a1x + b1y = c1
a2x + b2y = c2
Rankiniu būdu lygtį sprendžiame taikydami įvairius
metodus: keitimo, sudėties, įvesdami naujus kintamuosius ir pan.
Pasirenkame patogesnį (reikalaujantį mažiau veiksmų) metodą
konkrečiai lygčių sistemai spręsti priklausomai nuo jos
koeficientų. Programa turėtų būti universali ir tikti bet kokiai
lygčių sistemai spręsti. Veiksmų kiekis kompiuteriui mažiau
svarbus, negu žmogui. Todėl reikėtų pasirinkti kurį nors vieną
metodą, tinkamesnį programavimui. Toks metodas yra. Dviejų
tiesinių lygčių sistemos šaknį galima rasti pagal formules.
Pirmiausiai apskaičiuojami lygčių sistemos
determinantai (nepainiokime su kvadratinės lygties diskriminantu)
-
D = a1b2 - a2b1,
Dx = c1b2 - c2b1,
Dy = a1c2 - a2c1.
Jeigu D = 0 ir kuris nors iš Dx
arba Dy nelygus nuliui, tai lygčių sistema nesuderinama
ir sprendinių neturi.
Jeigu D = Dx = Dy = 0,
tai lygtys priklausomos ir jų sistema turi be galo daug sprendinių.
Jeigu netenkinama nė viena iš minėtų sąlygų,
tai lygties sprendiniai egzistuoja ir juos galima rasti pagal šias
formules:
-
x = Dx / D;
y = Dy / D
Šitaip galima išspręsti ne tik dviejų lygčių
sistemą su dviem nežinomaisiais, bet n tiesinių lygčių sistemą
su n nežinomųjų.
Parašykite programą dviejų tiesinių lygčių
sistemai spręsti.
3.5.2. Bikvadratinė lygtis
-
ax4 + bx2 + c = 0
sprendžiama įvedant pagalbinį kintamąjį
-
y = x2
Tada sprendžiama kvadratinė lygtis
-
ay2 + by + c = 0
o iš jos sprendinių gaunami bikvadratinės
lygties sprendiniai.
Parašykite programą bikvadratinei lygčiai
spręsti.
|
3.6. Veiksmų kartojimas. Ciklai while ir repeat
|
Programose būna veiksmų, kuriuos reikia kartoti. Dažniausiai
veiksmai yra tie patys, tik juos kartoti reikia vis su kitais
duomenimis.
Kartojimo veiksmai užrašomi ciklais. Paskalis turi trijų rūšių
ciklus. Jų antraštės prasideda baziniais žodžiais while,
for ir repeat. Todėl programuotojai kartais ciklus
taip ir vadina šiais baziniais žodžiais.
Ciklas while. Kartojimo veiksmus taikliausiai aprašo while
ciklas. Tai ir pats paprasčiausias ciklas. Jo veikimas grafiškai
pavaizduotas 23 paveiksle, o programoje užrašomas šitaip:
-
while loginis reiškinys do
sakinys
23 pav. Ciklo while schema
Pirmoji eilutė ciklo antraštė. Po jos
(t.y. po žodžio do) einantys sakinys kartojamas tol, kol
tenkinama ciklo antaštėje užrašyta sąlyga (kol loginio reiškinio
reikšmė yra true).
1 pavyzdys. Programa pirmajam reikšmingam
(t.y., nelygiam nuliui) skaičiaus skaitmeniui rasti.
-
program pirmasis;
var sk: integer;
begin
read(sk);
while sk > 9 do
sk := sk div 10;
writeln(sk)
end.
Šis uždavinys toks akivaizdus žmogui, kad jo
netgi nelaikome uždaviniu iš karto matome, koks pirmasis skaičiaus
skaitmuo. Tuo tarpu kompiuteryje skaičius būna užrašytas
dvejetainiais skaitmenimis ir kompiuteris dešimtainių skaičiaus
skaitmenų nemato, lygiai taip, kaip mes nematome dvejetainių
jo skaitmenų. Ir dar svarbiau užduotis kompiuteriui gali būti
išreiškiama tik tomis operacijomis, kurios yra programavimo
kalboje. O Paskalis turi tik aritmetines skaičių operacijas.
Paseksime, kaip šis ciklas atliekamas su įvairiais
pradiniais duomenimis.
Pradinis duomuo: 625.
-
sk
Sąlyga
read(sk)
625
sk >
9
true
sk := sk div
10
62
sk >
9
true
sk := sk div
10
6
sk >
9
false
writeln(sk)
Ciklas buvo atliktas du kartus.
Jeigu pradinis duomuo būtų dviženklis skaičius,
ciklas būtų atliktas vieną kartą. Jeigu pradinis duomuo būtų
vienženklis skaičius, ciklas nebūtų atliktas nė vieno karto
rezultatas būtų lygus pradiniam duomeniui.
Prieš kiekvieną sakinio kartojimą, perskaičiuojama
loginio reiškinio reikšmė ir pagal ją nustatoma, ar dar reikia
kartoti sakinį, ar jau užbaigti ciklą. Jeigu sąlyga netenkinama
(reiškinio reikšmė false) tikrinant ją pirmą kartą, tai
po žodžio do einantis sakinys neatliekamas nė karto. Taigi
galima tvirtinti, kad ciklas while gali būti atliekamas 0,
1, 2 ir daugiau kartų.
Ciklas valdo vieno sakinio kartojimą. Jeigu
reikia kartoti kelis sakinius, tai tie sakiniai sujungiami į vieną
sudėtinį sakinį.
2 pavyzdys. Programa skaičiaus skaitmenų
sumai rasti.
-
program SkSuma;
var sk, suma: integer;
begin
suma := 0;
read(sk);
while sk > 0 do
begin
suma := suma + sk mod 10;
sk := sk div 10
end;
writeln(suma)
end.
3 pavyzdys. Programa klasės mokinių pažymių
vidurkiui rasti.
-
program pvidurkis;
var
msk,
{ mokinių skaičius }
p,
{ vieno mokinio pažymys }
psuma:
integer; { visų
mokinių pažymių suma }
pbyla:
text;
{ pažymių byla }
begin
assign(pbyla, 'PAŽYMIAI.TXT'); reset(pbyla);
msk := 0;
psuma := 0;
read(pbyla, p);
while p > 0 do
begin
psuma := psuma + p;
msk := msk + 1;
read(pbyla, p)
end;
writeln(psuma/msk: 8: 2)
end.
Paeiliui skaitomi ir sudedami mokinių pažymiai.
Kartu skaičiuojamas ir mokinių (pažymių) skaičius msk.
Ciklas kartojamas tol, kol skaitomi pažymiai didesni už nulį. Todėl
čia nulis yra sutartinis ženklas. Juo užbaigiamas pažymių sąrašas.
Kai perskaitomas nulis, kompiuteris supranta, kad jau perskaityti
visi pradiniai duomenys (visų mokinių pažymiai), ciklą reikia
baigti ir jau galima skaičiuoti vidurkį. Nulis tai tik vienas
iš daugelio būdų nurodyti sąrašo pabaigai. Jis tinka tada, kai
sąraše nėra nulių. Šiam tikslui mes jį galėjome panaudoti tik
todėl, kad laikėme, kad pažymių, lygių nuliui, nebūna.
Ar kiekvienas ciklas turi pabaigą? Tam, kad
ciklas baigtųsi, reikia, kad jo antraštėje užrašyto loginio reiškinio
reikšmė kada nors taptų false. Vadinasi, loginio reiškinio
komponentus turi keisti sakinys. Priešingu atveju loginio reiškinio
rekšmė visą laiką išliks true ir ciklas niekada
nesibaigs. Toks ciklas vadinamas amžinuoju.
4 pavyzdys. Amžinasis ciklas kai nekeičiami
loginio reiškinio komponentai.
-
while a < b do
write(a)
5 pavyzdys. Amžinasis ciklas kai ne ta
linkme keičiami loginio reiškinio komponentai.
-
while a < b do
b := b + 1
Amžinasis ciklas yra dažnai pasitaikanti
klaida. Jeigu programa įtartinai ilgai veikia, tai galima tikėtis,
kad kompiuteris atlieka amžinąjį ciklą. Tokiu atveju programos
darbą reikia priverstinai nutraukti (daugelyje kompiuterių
paspausti klavišus Ctrl+Break) ir ieškoti klaidos
amžinojo ciklo.
Ciklas repeat. Kitas, rečiau vartojamas
ciklas yra vadinamas repeat ciklu. Jo pavidalas yra šitoks:
-
repeat
sakinys1;
sakinys2;
...
sakinysn
until loginis reiškinys
Sakiniai,
esantys tarp žodžių repeat ir until, kartojami iki
tol, kol bus patenkinta sąlyga loginio reiškinio reikšmė
taps true.
Ciklo veiksmai grafiškai parodyti 24
paveiksle.
24 pav. Ciklo repeat schema
6 pavyzdys. Programa, skaičiuojanti sumą
skaičių sekos, kurios paskutinis skaičius sutampa su pirmuoju.
Skaičiai renkami klaviatūra.
-
program suma;
var sk,
{ skaitomas skaičius }
pirmas,
{ pirmas perskaitytas skaičius }
sum:
integer;
{ suma }
begin
read(pirmas);
sum := pirmas;
repeat
read(sk);
sum := sum+sk
until sk = pirmas;
writeln(sum)
end.
Cikle repeat pirma atliekami veiksmai, o
po to tikrinama sąlyga. Dėl to ciklas visada atliekamas bent vieną
kartą. Taigi galima tvirtinti, kad ciklas repeat gali būti
atliekamas 1, 2, 3 ir daugiau kartų.
Ciklas repeat baigiamas, kai tenkinama
jo pabaigoje (po žodžio until) parašyta sąlyga. Tuo tarpu
ciklas while baigiamas kai nebetenkinama jo pradžioje parašyta
sąlyga. Šios dvi priešingybės kartais supainiojamos ir
programuotojas suklysta. Galime pasiūlyti tokį lengviau įsimenamą
sąlygų tikrinimo modelį. Vietoj sąlygų įsivaizduokime šviesoforus.
Kai sąlyga tenkinama, šviesoforas žalias, kai netenkinama
raudonas.
Šviesoforas stovi ciklo while pradžioje.
Vadinasi, patekti į ciklą galima kai šviesoforas žalias sąlyga
tenkinama.
Šviesoforas stovi ciklo repeat
pabaigoje. Vadinasi, jis reguliuoja išvažiavimą iš ciklo. Taigi
ciklą palikti galima kai šviesoforas žalias sąlyga
tenkinama.
Žodis until atlieka ir skyrybos ženklo
vaidmenį parodo, kur baigiasi ciklo sakiniai. Dėl to cikle repeat
galima rašyti daugelį sakinių nereikia jų apskliausti
Uždaviniai
3.6.1. Kokia bus kintamojo x reikšmė,
atlikus šitokias sakinių sekas?
-
a) k := 1;
while k < 5 do
k := k + 1;
x := k
-
b) x := 1;
while x <= 5 do
x := x + 1;
3.6.2. Duota sakinių seka
-
a := 1; b := 1;
while a+b < 8 do
begin
a := a+1;
b := b+2
end;
s := a+b
-
Kiek kartų bus atliekamas ciklas ir kokios
bus kintamųjų a, b ir s reikšmės, atlikus duotąją sakinių
seką?
3.6.3. Kokios bus kintamųjų a ir b
reikšmės, atlikus šią sakinių seką:
-
a := 1; b := 1;
while a <= 3 do
a := a+1; b := b+1
3.6.4. Parašykite programą, kuri rastų
mažiausią skaičių byloje SKAIČIAI.TEK.
Praktikos darbas
3.6.1. Rezultatų kaita atliekant programą.
3 pavyzdžio programą pvidurkis modifikuokite taip, kad ji apskaičiuotų
per pamoką gautų mokinių pažymių vidurkį dinamiškai, t.y., pažymių
sąrašas papildomas, kai tik pažymį gauna nauja mokinys ir
kiekvieną kartą ekrane parodomas naujas, pakoreguotas vidurkis.
Atlikite ją kompiuteriu.
|
3.7. Valdymo struktūrų palyginimas
|
Prieskyros, duomenų skaitymo bei rašymo ir tuščias
sakinys yra elementarūs, nedalomi. Į juos negali įeiti jokie kiti
sakiniai.
Sakinių atlikimo tvarką nustato struktūriniai
sakiniai sudėtinis, sąlyginis ir ciklo. Jie sudaromi iš
elementarių ir trumpesnių struktūrinių sakinių.
Kelių sakinių seką sudėtinis sakinys paverčia
vienu sakiniu. Todėl visur ten, kur pagal programavimo kalbos
taisykles gali būti rašomas tik vienas sakinys, o norisi rašyti
kelis sakinius, tuos kelis sakinius reikia sujungti į vieną sudėtinį,
ir problema bus išspręsta.
Visą programą sudaranti sakinių seka taip
pat jungiama į vieną sudėtinį sakinį. Taigi galima tvirtinti,
kad visos programos veiksmai išreiškiami vienu sudėtiniu sakiniu.
Žinoma, tas sakinys gali būti sudėtingas ir ilgas užimti
daug puslapių.
Sąlyginis sakinys išrenka vieną kurią nors
programos šaką. Kitos šakos sakiniai neatliekami. Vadinasi,
kompiuteris atlieka mažiau sakinių negu jų yra programoje.
Ciklų sakiniai nurodo, kad reikia ciklo
sakinius kartoti daug kartų. Vadinasi, kai programoje yra ciklų,
kompiuteriui gali tekti atlikti daugiau veiksmų negu jų yra parašyta
programoje.
Struktūriniai sakiniai dar vadinami valdymo
struktūromis, nes jais išreiškiami nurodymai, kaip valdyti kitų
sakinių atlikimo tvarką. Visos nagrinėtos valdymo struktūros yra
lygiateisės: jos gali įeiti viena į kitą. Nuosekli sakinių seka
jau buvo pakeista vienu sudėtiniu sakiniu, įeinančiu į ciklą
arba sąlyginį sakinį. Patys sąlyginiai sakiniai arba ciklai buvo
eiliniai nuoseklios sakinių sekos nariai. Ciklas taip pat gali būti
kitame cikle arba sąlyginiame sakinyje be jokių ribojimų.
1966 m. C. Bohmas ir G. Jacopinis įrodė, kad
kiekvieną elementarių sakinių atlikimo tvarką galima aprašyti
trimis valdymo struktūromis: sakinių seka, sąlyginiu sakiniu
ciklu. Pakanka tik vienos rūšies (nesuprastinto) sąlyginio
sakinio ir vienos rūšies (while) ciklo. Kiti (alternatyvūs)
struktūriniai sakiniai nėra būtini. Tačiau jie sutrumpina
programą arba padaro ją vaizdesnę. Prieš rašant struktūrinį
sakinį reikia pagalvoti, kurią iš galimų alternatyvių valdymo
struktūrų naudoti. Pasirinkus tinkamą struktūrą, programa bus
trumpesnė, ją bus lengviau skaityti.
Uždaviniai
3.7.1. Kurie iš šių teiginių
teisingi?
-
a) ciklas prasidedantis žodžiu while
gali būti neatliktas nė vieno karto;
b) ciklas prasidedantis žodžiu repeat gali būti
neatliktas nė vieno karto;
c) ciklas prasidedantis žodžiu while arba repeat
gali būti atliktas vieną kartą.
3.7.2. Palikite vieną iš skliaustuose
parašytų alternatyvų:
-
Ciklo sakinys, prasidedantis žodžiu while
valdo (vieno sakinio / sakinių sekos) kartojimą, o ciklo
sakinys, prasidedantis žodžiu repeat valdo (vieno
sakinio / sakinių sekos) kartojimą.
|
3.8. Begalinių eilučių sumavimas
|
Daugelį matematikos konstantų arba funkcijų
galima išreikšti begalinių eilučių suma. Pateiksime pavyzdžių:
-
1 1
1
1
e = 1 + + + + . . . + . . .
1! 2!
3!
n!
-
x x2 x3
xn
ex = 1 + + + + . . . + . . .
1! 2!
3!
n!
(e natūrinių logaritmų pagrindas)
-
p
1 1
1 xn
= 1 - + - + . . . . . .
4
3 5
7 n!
-
x3 x5 x7
arctg x = x - + - +
3 5! 7!
Kuo daugiau eilutės narių sudėsime
(kompiuteriui nesunku sudėti jų labai daug), tuo tikslesnę reikšmę
gausime. Kiek jų reikia sudėti, programoje galima nurodyti įvairiai.
Paprasčiausia sumuoti tam tikrą iš anksto nustatytą pirmųjų
narių skaičių. Tačiau programos dažniausiai sudaromos taip, kad
būtų sumuojami eilutės nariai tol, kol jie pasidaro mažesni už
tam tikrą, labai mažą, iš anksto pasirinktą dydį. Šis dydis
ir apibūdina paklaidą.
Pavyzdys. Sudarysime programą natūrinių
logaritmų pagrindui e rasti.
-
program logaritmas;
const epsilon =
1E-6; { liekamasis
narys }
var k : integer;
e, narys: real;
begin
e := 0.0;
narys := 1.0;
k := 1;
while narys >= epsilon do
begin
e := e + narys;
narys :=
narys/k; { 1/1 }
{1/1/2 = 1/(1*2)}
{1/1/2/3 = 1/(1*2*3)}
{ . . . }
k := k + 1
end;
writeln(e)
end.
Šioje programoje skaičiaus faktorialas neskaičiuojamas
išreikštiniu būdu. Eilinis eilutės narys gaunamas ankstesnį jos
narį padalijus iš vieno po kito einančių natūraliųjų skaičių.
Taip išvengiama didelių skaičių faktorialų reikšmių, kurios
gali netilpti į sveikųjų skaičių rėžius.
-
Kompiuteris, atlikęs programą logaritmas,
pateikė šitokį rezultatą:
2.7182815256E+00
-
Palyginimui pateikiame tikslesnę skaičiaus
e reikšmę:
2,7182818284.
Programose, kurių rezultatai yra sveikieji
skaičiai, reikia vengti realiųjų skaičių, nse operacijos su
jais rezultatai yra apytiksliai skaičiai ir gali iškreipti tikrąjį
rezultatą. Pavyzdžiui, jei skaičiuodami sklypo plotą vietoj 8191
m2 gauname 8191,5 m2 arba 8191 m2,
tai į tokia menkas paklaidas galime nekreipti dėmesio. Tuo tarpu
jeigu pirminių skaičių ieškojimo programoje vietoj 8191 gautume
8192, tai toks rezultatas ir jį duodanti programa būtų klaidingi.
Uždaviniai
3.8.1. Parašykite programą funkcijos
ex reikšmei rasti, taikydami skyrelio pradžioje pateiktą
eilutės sumavimo
formulę.
3.8.2. Parašykite programą skaičiaus p
reikšmei rasti, taikydami skyrelio pradžioje pateiktą
eilutės sumavimo
formulę. Sumuoti reikia tol, kol eilutės nario modulis bus mažesnis
už 1010.
|
E Ankstesnis
puslapis |
3
Turinys |
Kitas
puslapis F |
|
|
|
|