Motto: Cimrmanova hra Švestka je hrou o stáří. K neduhům stáří, postihujícím hlavně intelektuály, patří především dvě vady, komplementárně spojené. Je to: neschopnost udržet myšlenku a druhá vada: neschopnost myšlenku opustit.
Předmluva | ↑ ↓ |
Zejména druhá vada z úvodního citátu sužuje stránky RPNmania nejvíce. Jejich autor, i když není intelektuálem ani v nejmenším, přes veškeré uvědomění si vážnosti situace není schopen opustit myšlenku na postup převodu římských čísel na arabská a naopak. Posedlost tímto tématem je tak úporná, že zde předkládané řešení této úlohy je v pořadí již čtvrté! Pokud by byl někdo přemrštěným počtem opakovaných návratů ke stále stejnému problému konsternován natolik, že by se zdráhal této skutečnosti uvěřit, zde je výčet dosavadních pokusů o toto řešení:
Tak. A je to venku. Po dlouhodobém přešlapování (s jednou čestnou výjimkou) je tu pořádný RPN program! Přídavné jméno "pořádný" je v minulé větě použito oprávněně. Půst si vybral svou daň a projevil se velikostí nového přírůstku do stáda - 270 řádků kódu! Poručík Hamáček by na tomto místě dozajista položil svoji oblíbenou řečnickou otázku: „A z toho máme všichni co?“ Jako obvykle by se mu z řad mužstva nedostalo kýžené odezvy, odpověděl by si proto rezignovaně sám: „Z toho máme všichni radost.“
Řešení | ↑ ↓ |
Nadměrné množství euforie tryskající z předmluvy musí nutně budit podezření. Každý jistě ví, že zpracování římských čísel je na HP-50g snadné. Množství různých datových typů - včetně textových/znakových řetězců - umožňuje provádět téměř cokoliv. Co ale HP-35s? Vždyť v porovnání s tou RPL obludou je to pouze "mlejn na čísla"! Co tedy s těmi písmeny?
Jako první se samozřejmě nabízela možnost využít zobrazení hexadecimálních číslic. Jenže z požadovaných sedmi I-V-X-L-C-D-M jsou k mání pouze dvě. Má smysl dva znaky ze sedmi ponechat a zbývající nahradit ciframi? To jistě ne. Nechť je tedy nahrazeno všech sedm znaků dekadickými ciframi. Následující tabulka zobrazuje příslušné náhrady.
Originál | I | V | X | L | C | D | M |
---|---|---|---|---|---|---|---|
Hodnota | 1 | 5 | 10 | 50 | 100 | 500 | 1000 |
Náhrada | 1 | 5 | 2 | 7 | 3 | 9 | 4 |
Že písmeno I nahrazuje cifra 1 a že V je zastoupeno 5, se dá snadno pochopit. Další zdůvodnění náhrad už ale poněkud pokulhávají. Přesto nejsou zástupné cifry určeny "generátorem náhodných čísel" ani - v tomto případě rovnocennou - "střelbou od boku". Následující odstavec se pokouší zvolený systém náhrad obhájit.
Římské znaky I, X, C, M mají hodnoty vždy začínající cifrou 1. Jsou tedy prostě očíslovány 1, 2, 3, 4. (Tyto hodnoty zároveň určují počty cifer dekadických ekvivalentů.) Absolventu Matematicko-fyzikální fakulty by toto jednoduché zdůvodnění patrně nestačilo. Proto je zde výhradně pro něj nachystán vzorec definující vztah mezi zástupnou římskou cifrou r a její hodnotou v:
v = 10 r - 1
Vysvětlení volby zbývajících dvou zástupných cifer je ještě kostrbatější. Sedmička otočena vzhůru nohama připomíná literu L. Devítka má na pravé straně oblouk, podobně jako písmeno D. Žádnou slávu neznamená ani fonetická podobnost začátků slov Déčko - Devítka...
Pozn.: Pokud by někdo za náhradu písmen I-V-X-L-C-D-M preferoval jiná čísla, než 1-5-2-7-3-9-4, může program v tomto ohledu modifikovat velmi snadno. Podprogram na adrese R269 (symbolicky označený sub_sromt) vrací jako sortiment náhrad číslo 4937251. Může však vracet libovolné jiné sedmiciferné číslo neobsahující nulu.
Dalším úskalím v případě HP-35s je nemožnost rozlišení vstupní hodnoty. Tady nelze nějakým způsobem otestovat typ objektu v X-registru RPN stacku. Je tam prostě nějaké číslo a basta. I kdyby tam bylo něco jiného (komplexní číslo nebo vektor), nebude jednoduché to rozlišit. Nejjednodušším řešením bylo rozdělení číselného oboru na dvě poloviny:
Navzdory očekávání vzorem pro RPN program nebyla UserRPL verze, ale zbývající dvě podoby: v jazyku C a v assembleru (všechny zmíněné v Předmluvě). Pokud tímto konstatováním někdo zůstal zcela nevzrušen, nesetrvá v takovém blazeovaném stavu dlouho. Stačí si uvědomit, že veškeré bitové (nebo nibbleové) posuny a logické operace AND/OR jsou zde nahrazeny exponenciální funkcí 10 x, různým násobením, dělením a oddělování tu celé jindy desetinné části čísel. Výsledek tomu odpovídá: program je neúměrně dlouhý (to rozhodně nepotěší - por. Hamáček neměl tak úplně pravdu :-) a jeho provádění trvá naprosto nesmyslně dlouhou dobu. Ale o to naštěstí nejde - času na blbosti máme dost a "pětatřicítka" má paměti na rozdávání!
Program má dvě hlavní větve. Podle očekávaní to jsou PŘEVOD A→R a PŘEVOD R→A. Kromě toho je na úplném začátku rozskok podle typu vstupní hodnoty a na samém konci lze nalézt shluk podprogramů využívaných oběma hlavními větvemi. Převod A→R v podstatě kopíruje funkci a2r() z modulu roman.c. Opačný převod R→A vychází z funkce r2a2(), k vidění je v r2a2.c. Následující odstavce upozorňují na zvláštnosti těchto programových bloků. Před začátkem těchto odstavců je třeba vyzdvihnout důležitý fakt: Celý program používá jedinou statickou/globální proměnnou (nebo postaru paměťový registr) - I. Ostatní mezivýsledky jsou ukládány v obou hlavních větvích odlišně.
PŘEVOD A→R je tím jednodušším z dvojice převodů. V RPN realizaci je počet lokálních proměnných nižší, než naznačuje zmiňovaná funkce a2r(), předobraz tohoto řešení. Proměnné divisor, sidx a ridx zde nemají ekvivalent. Poli result[] odpovídá proměnná I. Ostatní mezivýsledky jsou sdruženy (a USCHOVÁNY) do vektoru, který je ve výpisu programu označen identifikátorem SAFE, a stále se "potlouká" někde v RPN stacku. Hodnoty ve vektoru jsou:
c . . . . . | Aktuální cifra ze zadání. Je to cifra nejvyššího řádu. |
v . . . . . | Zbývající hodnota (bez cifry c). |
k2 . . . . | Kvadrát dekadického násobku nejvyššího řádu. (Na jeden dekadický řád připadají dvě římské cifry.) |
PŘEVOD R→A je složitější a tomu odpovídají i zvýšené nároky na počet lokálních proměnných. Zde jejich počet a účel takřka kopíruje obsah funkce r2a2(): aidx, pidx, less a dvě pole addt a subt nemohou být vměstnány ani do dvou vektorů, natož ponechávány na RPN stacku. Ke slovu se nutně musela dostat u jiných kalkulátorů ne zcela obvyklá vlastnost: "bazén" (v originále pool) plný bezejmenných, nepřímo adresovatelných registrů. Zde je jejich obsazení:
Index/adresa | 0 | 1..4 | 5..8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|
Význam | římská cifra | addt[] | subt[] | less | předchozí index | zbývající hodnota | zadání |
Pozn.: Využití nepřímo adresovatelných registrů vysvětluje, proč jedinou veřejnou proměnnou v celém programu není třeba R, ale právě I (ještě tak J by přicházelo v úvahu :-).
Pozn.: Program v módu R→A zabere prvních 13 bezejmenných registrů bez ohledu na jejich možné aktuální zaplnění. Testovat zaplněnost "bazénu" registrů pro stanovení bázové adresy by bylo asi samoúčelné. Premisa ať si každý program dělá co chce bez ohledu na ostatní přináší nezanedbatelnou výhodu: bázová adresa bude vždy 0. Po ukončení běhu programu (úspěšném i havarijním) je alokované místo použitých registrů uvolněno (viz podprogram r2a_clean).
Při nesprávně zadané vstupní hodnotě (příliš velké číslo při převodu A→R, neznámé zástupné znaky, nesprávné pořadí znaku atd. v případě R→A) zobrazí displej HP-35s dvě hodnoty. V Y-registru RPN stacku je nezměněné zadání, v X-registru je chybová hodnota. Pozná se podle toho, že je to číslo s desetinnou částí. Celá část určuje index (dekadický řád, pořadí) chybného znaku v zadání. Desetinná část rozlišuje chybu. Významy jsou zachyceny v následující tabulce:
Převod | Hodnota | Význam |
---|---|---|
A→R | 0.1 | Zadaná hodnota je mimo rozsah 1 až 3999 |
R→A | 0.2 | Neznámá římská cifra |
0.3 | Neočekávaná římská cifra | |
0.4 | Příliš mnoho předchozích římských cifer stejného řádu |
RPN program | ↑ ↓ |
Použití programu:
Stisk kláves | Činnost | Display |
---|---|---|
1 9 7 8 | zadání | 0.0000 1978_ |
XEQ R ENTER | spuštění programu | RUNNING |
výsledek... | 0.0000 -4,347,225,111.00 | |
XEQ R ENTER | ...použit jako zadání | RUNNING |
výsledek | 0.0000 1,978.0000 | |
4 5 6 7 | chybné zadání | 1,978.0000 4567_ |
XEQ R ENTER | spuštění programu | RUNNING |
chybové hlášení | 4,567.0000 0.1000 | |
2 7 8 5 1 1 +/- | další chybné zadání | 0.1000 -278511_ |
XEQ R ENTER | spuštění programu | RUNNING |
chybové hlášení | -278,511.0000 3.2000 | |
2 7 5 1 1 +/- | správné zadání | 3.2000 -27511_ |
XEQ R ENTER | spuštění programu | RUNNING |
výsledek | 0.0000 47.0000 |
Závěr | ↑ ↓ |
Prezentovaný program je bezkonkurenčně nejnepoužitelnější z toho, co stránky RPNmania nabízejí. Všechny předchozí tvořily více či méně roztomilé krátké ukázky, které bylo snadné do kalkulátoru zadat a doba jejich provádění byla tak krátká, že kalkulátorův uživatel se ani nestihl začít nudit. Zato tenhle moloch! Hanba mluvit... Ale nad tím by se dalo mávnout rukou, kdyby ten program byl alespoň trochu použitelný. V praktické použitelnosti snad nebrání dlouhá doba výpočtu. Ani nahrazení písmen číslicemi by tolik nevadilo. Hlavní nevýhodou programu je to, že ve stanoveném rozsahu 1..3999 nelze ani zadat ani zobrazit všechna čísla v římské notaci! Maximální počet cifer mantisy u HP-35s je 12. Nejdelší římské číslo je 3888 = MMMDCCCLXXXVIII, tedy řetězec o délce 15 znaků. Vzhledem k charakteru zápisu římských čísel nelze ani stanovit souvislý rozsah číselné hodnoty vyjádřený čísly arabskými. Ověřit si správnost obou převodů lze opakovanými převody tam a zpět. Pokud se při opakovaném převodu dosáhne hdonoty shodné se zadáním, je vše v pořádku. V opačném případě má uživatel smůlu a zbývá mu poslední možnost: přestat blbnout a vytáhnout HP-50g.
Pozn.: Samozřejmě by bylo možné čísla římské notace s délkou větší než 15 znaků rozdělit do dvou či více hodnot. Ale to už by byla magořina dalece přesahující zdejší poměry. Obzvláště zadávání takového vstupního údaje by pro obsluhu mohlo být velmi dobrodružné!
Jistě se někomu bude zdát pošetilé vytváření programů, které už z principu nemohou plnohodnotně fungovat. V tom však není hlavní problém stránek RPNmania. Na hranici použitelnosti (ne-li hluboko pod ní) je všechno, co je zde prezentováno, i když to regulérně funguje. Na zřeteli je však třeba mít důležitou myšlenku: O funkčnost ani užitečnost zde nikdy nešlo! Proč tedy celé to běsnění? Je to přece "čelinž", ne?!