6.4. Společné vlastnosti aritmetických příkazů Všechny aritmetické příkazy (COMPUTE, ADD, SUBTRACT, MULTIPLY a DIVIDE) mají určité společné vlastnosti, které je vhodné popsat společně. Jsou to: a) význam klauzule ROUNDED; b) význam klauzule ON SIZE ERROR; c) způsob dosazení výsledku aritmetického výrazu do příjmové položky (tak nazýváme položku, která je příkazem naplňována); d) činnost při více příjmových položkách. Činnost každého z aritmetických příkazů probíhá dle následujícího schématu: 1) Nejdříve se vypočítá hodnota příslušného aritmetického výrazu (a to tak, aby pokud možno nedošlo ke ztrátě platných cifer za desetinnou tečkou; ke ztrátě platných cifer před desetinnou tečkou nemůže nikdy dojít). Tento aritmetický výraz je u příkazu COMPUTE uveden explicitně, zatímco u ostatních aritmetických příkazů je vždy určen formátem příkazu. 2) Klauzule ROUNDED se může uplatnit jen tehdy, když ani výsledek aritmetického výrazu ani příjmová položka nejsou v exponenciálním tvaru. Klauzule ROUNDED pak způsobí, že výsledek aritmetického výrazu bude před přesunem do příjmové položky zaokrouhlen. Zaokrouhlování lze ovšem provádět pouze tehdy, má-li výsledek aritmetického výrazu vzadu (tj. za desetinnou tečkou) více cifer než příjmová položka (tzn. když při přesunu mají být nějaké cifry výsledku odřezávány). Zaokrouhlováním se rozumí, že cifra výsledku odpovídající nejnižšímu dekadickému řádu příjmové položky bude zvýšena o 1, pokud následující cifra výsledku (tj. první odřezávaná cifra) je větší nebo rovna 5. Případné přenosy do vyšších řádů výsledku se samozřejmě provedou. Je-li výsledek aritmetického výrazu anebo příjmová položka v exponenciálním tvaru, klauzule rounded se ignoruje; v tomto případě se totiž při přesunu výsledku aritmetického výrazu do příjmové položky vždy provádí vhodný způsob zaokrouhlování, které nemůže být potlačeno (viz 6.1.). Příklad: výsledek PICTURE zaokrouhlený aritm. výrazu příjmové položky výsledek ---------------------------------------------------------- 123 999 123 24.49 999 24 -3.45 S99V9 -3.5 999.96 9999V9 1000.0 0.0052 P9 0.01 1264.2 99PP 1300 3) Není-li uvedena klauzule ROUNDED, neprovádí se žádné zvláštní zaokrouhlování výsledku aritmetického výrazu. Pokud tedy ani výsledek aritmetického výrazu ani příjmová položka nejsou v exponenciálním tvaru, budou případné přebytečné cifry výsledku aritmetického výrazu vzadu (tj. za desetinnou tečkou) při přesunu do příjmové položky odříznuty, tak jak to vždy provádí příkaz MOVE (viz 6.1.). 4) Není-li uvedena klauzule ON SIZE ERROR, bude výsledek aritmetického výrazu bez jakékoliv kontroly přesunut do příjmové položky. Přesun se provádí jako numerický přesun u příkazu MOVE (viz 6.1.), budou tedy případné přebytečné cifry výsledku vlevo (před desetinnou tečkou) odříznuty, aniž by o tom uživatel dostal nějakou informaci. 5) Je-li uvedena klauzule ON SIZE ERROR, před přesunem se nejprve zjistí, zda výsledek aritmetického výrazu (včetně zaokrouhlení, je-li současně uvedena i klauzule ROUNDED) nemá vpředu (tj. před desetinnou tečkou) více platných cifer, než kolik je jich předepsáno v PICTURE příjmové položky: a) Pokud ano, výsledek se nepřesune do příjmové položky (její hodnota tedy zůstane beze změny) a budou se provádět příkazy uvedené za ON SIZE ERROR. b) Pokud ne, bude výsledek přesunut do příjmové položky (dle pravidel numerického přesunu u příkazu MOVE), příkazy uvedené za ON SIZE ERROR se přeskočí a jako další se bude provádět první příkaz za tečkou. Je-li příjmová položka exponenciální, klauzule ON SIZE ERROR se nikdy neuplatní, nýbrž vždy se odskočí za tečku. Poznámka: Je-li v příkazu uvedeno několik příjmových položek, pak pro kterékoliv z nich mohou být uvedeny klauzule ROUNDED. Každá klauzule ROUNDED se vztahuje pouze na dosazování výsledku do té jediné příjmové položky, za níž je uvedena; nelze zadat "společnou" klauzuli ROUNDED pro několik příjmových položek dohromady. Poznámka: Klauzule ON SIZE ERROR má dvě funkce: jednak se uplatní při dosazování výsledku celého aritmetického výrazu do příjmové položky (viz bod 5), a jednak způsobí, že při výpočtu aritmetického výrazu se před každým dělením položkou nebo mezivýsledkem zjistí, zda dělitel není nulový; pokud by byl nulový, nebude se pokračovat ve výpočtu aritmetického výrazu a hned se uplatní klauzule ON SIZE ERROR (týká se příkazu COMPUTE, obsahuje-li aritmetický výraz dělení položkou nebo mezivýsledkem, a příkazu DIVIDE, je-li dělitelem položka). Poznámka: Při výpočtu mezivýsledků i celkového výsledku aritmetického výrazu nemůže dojít ke ztrátě platných cifer vpředu (tj. před desetinnou tečkou); kdyby kvůli zabránění nebezpečí ztráty platných cifer vpředu bylo nutno příliš snížit počet uchovávaných platných cifer vzadu (tj. za desetinnou tečkou), bude celý výpočet převeden do exponenciálního dlouhého tvaru. Kdyby nebylo možno mezivýsledek resp. výsledek zobrazit ani v exponenciálním dlouhém tvaru (na počítačích typu PC je tomu tak při přesáhnutí 8.988 * 10**307), dojde k chybě a k ukončení výpočtu. Příklad: Má-li položka A PIC 99 a hodnotu 95, pak při provádění příkazu COMPUTE A = A + 8 ON SIZE ERROR DISPLAY A. se klauzule ON SIZE ERROR uplatní (výsledek 103 má více než dvě cifry před desetinnou tečkou), takže příkaz DISPLAY vytiskne nezměněnou hodnotu 95. Příklad: Má-li položka B PIC 999, pak při provádění příkazu COMPUTE B = 999.5 ON SIZE ERROR ... se klauzule ON SIZE ERROR neuplatní a do položky B se dosadí hodnota 999. Naproti tomu při provádění příkazu COMPUTE B ROUNDED = 999.5 ON SIZE ERROR ... bude po zaokrouhlení výsledek 1000 a klauzule ON SIZE ERROR se tedy uplatní! Poznámka: Je-li uvedena klauzule ON SIZE ERROR u příkazu s několika příjmovými položkami nebo s klauzulí CORRESPONDING, provedou se postupně všechny dílčí příkazy, na něž se původní příkaz rozkládá, přičemž se však výsledek dosazuje do příjmové položky jen u těch dílčích příkazů, u nichž nedošlo k přeplnění. Pokud v alespoň jednom dílčím příkazu dojde k přeplnění, budou se po provedení všech dílčích příkazů provádět příkazy uvedené za ON SIZE ERROR. Pokud v žádném dílčím příkazu nedojde k přeplnění, pak po provedení všech dílčích příkazů se přeskočí příkazy uvedené za ON SIZE ERROR a bude se provádět první příkaz za tečkou. 6) Je-li uvedeno více příjmových položek, vypočítá se nejprve ta část aritmetického výrazu, která je pro všechny tyto příjmové položky společná, a uloží se do pomocného mezivýsledku. Tato společná část aritmetického výrazu vypadá takto: a) U příkazu COMPUTE a u příkazu s klauzulí GIVING je to hodnota celého příslušného aritmetického výrazu. b) U příkazu ADD s TO je to součet operandů mezi ADD a TO. c) U příkazu SUBTRACT bez GIVING je to součet operandů mezi SUBTRACT a FROM. d) U příkazu MULTIPLY bez GIVING je to násobitel (uvedený za slovem MULTIPLY). e) U příkazu DIVIDE bez GIVING je to dělitel (uvedený za slovem DIVIDE, neboť při více příjmových položkách se nutně jedná o formát s INTO). Ve všech případech platí, že je-li společnou částí aritmetického výrazu jediný operand, který jest literálem, nepřesunuje se do pomocného mezivýsledku, nýbrž pro každou příjmovou položku se zvlášť upraví do nejvhodnějšího tvaru pro příslušnou operaci. Pokud se hodnota pomocného mezivýsledku získává výpočtem, bude formát pomocného mezivýsledku určen pravidly uvedenými v kapitole 6.10. Přesunuje-li se do pomocného mezivýsledku jediná položka, bude pomocný mezivýsledek celočíselný binární nebo exponenciální dlouhý v závislosti na typu této položky a na formátu příkazu. Pak se pro jednotlivé příjmové položky postupně provádí: a) U příkazu COMPUTE a u příkazů s klauzulí GIVING přesun pomocného mezivýsledku do každé příjmové položky. b) U příkazu ADD resp. SUBTRACT resp. MULTIPLY resp. DIVIDE bez klauzule GIVING zvětšení resp. zmenšení resp. vynásobení resp. vydělení každé příjmové položky pomocným mezivýsledkem. Poznámka: Z pravidel uvedených v bodě 6) vyplývá, že byla-li některá z příjmových položek současně použita i pro výpočet pomocného mezivýsledku, nezpůsobí dosazení příslušné hodnoty do ní nový výpočet pomocného mezivýsledku. Původně vypočítaná hodnota pomocného mezivýsledku se použije nezměněně i pro výpočet následujících příjmových položek. Příklad: Nechť A = 1, B = 10, C = 100. Pak příkaz ADD A B C TO A B C bude přeložen jako COMPUTE POM = A + B + C ADD POM TO A ADD POM TO B ADD POM TO C což dá výsledné hodnoty A = 112, B = 121, C = 211. Naproti tomu kdybychom náš příkaz ADD sami rozdělili tímto způsobem: ADD A B C TO A ADD A B C TO B ADD A B C TO C vyšly by odlišné hodnoty, a to A = 112, B = 232, C = 544.