Ako na cisla v plavajucej desatinnej ciarke ?

     Ti, ktori listuju BASIC nielen pomocou prikazu LIST ale aj nejakym monitorom, sa uz urcte stretli so systemom kodovania vsetkych ciselnych hodnot. Prave pre tych je urceny nasledujuci program.
     Vsetky cisla su kodovane do 5 bajtov. Pokial je to cele cislo v rozsahu -65535 az 65535, nie je ziadny problem ho precitat. Prvy bajt vyjadruje znamienko (0:+, 255:-), druhy je nulovy, treti je nizsi bajt tohto cisla a stvrty je vyssi bajt. Na poslednom piatom bajte nezalezi, ale pre prehladnost sa tam zvykne davat nula. Vdaka takemuto usporiadaniu nie je problem toto cislo precitat z lubovolneho monitora.
     Ale co ak je to cislo v plavajucej desatinnej ciarke ? Z pameti na vas hladi pet vseobecnych bajtov a vy v okamihu neviete, ci mate pocitac resetnut alebo ho radsej rovno vytiahnut z prudu.
     No, az take hrozne to zase nie je, lebo sa tu ponukaju hned dve skupiny moznosti ako toto cislo zistit. Podla prvej skupiny (nazvime ju "Analyticke sposoby") sa vypocita hodnota cisla podla nasledujuceho postupu:

     Toto je sice pekny sposob, ale uprimne: chcelo by sa vam to zakazdym pocitat ? Dalo by sa to urobit na programovatelnej kalkulacke, ale ani to nie je velka vyhra, lebo aj na tej najprogramovatelnejsej kalkulacke by ste museli do nej klepat tych 5 bajtov. Navyse kalkulacky maju obvykle inu presnost vypoctu a preto by sa mohla vypocitana hodnota lisit od skutocnej. Istym riesenim by bolo tento vypocet naprogramovat do basicu, napriklad takto:

LET c=2*(.5+PEEK (add+1)/256 + PEEK (add+2)/65536 + PEEK (add+3)/16777216 + PEEK (add+4)/4.2949673e9) * 2^(PEEK add-129)

     Tento sposob je pouzity aj v programe Rexo. Avsak nesie zo sebou jeden obrovsky hacik. Pre cisla bliziace sa maximalnej zobrazitelnej hodnote 1.7014118*10^38 tento vyraz fungovat nebude, pretoze medzivysledky vypoctu vyssie spomenuteho vyrazu mozu presiahut spomenutu maximalnu hodnotu. Tento vyraz by sa dal upravit tak, aby to nenastalo, ale to by so sebou prinieslo trochu nizsiu presnost vypoctu.

     Druhu skupinu moznosti nazvime "Zdravy sedliacky rozum". Vychadzajme z toho, ze basic si vie poradit s tymito piatimi bajtami. No a tychto nasich 5 bajtov mu proste "podstrcime". Najjednoduchsie sa to urobi tak, ze do prveho riadku v basicu napiseme PRINT 0 (vtedy si on v pameti vyhradi pet bajtov, kam hned ulozi hodnotu tej nuly) a potom mu do tychto piatich bajtov napokujeme nasich pet bajtov. Nakoniec basic spustime a prikaz PRINT nam vypise nasu tuzobne ocakavanu hodnotu.
     Funguje to preto, lebo ked bezi basicovy program, ako hodnoty cisel sa neberu tie, co vidno pri listingu ale tie, ktore su definovane piatimi bajtami v pameti (toto sa velmi casto zneuziva vo vseliakych ochranach). Adresa basicu je za normalnych okolnosti na 23755 a tych pet bajtov je o sedem bajtov dalej po kode 14.

     Avsak aj toto bol dost pracny sposob. Musite zasahovat do basicoveho programu (co je nie vzdy mozne) a pokovat tych pet bajtov. Nasledujuci program vsetky tieto nevyhody odstranuje. Ma len 7 bajtov, takze ani nebude problem si ho rucne napokovat.

E1 pop hl 
2A 76 5C   ld hl,(#5c76) 
C3 B4 33   jp #33b4 
   

V dekadickom tvare: 225, 42, 118, 92, 195, 180, 51.

     Ked budete mat tento program v pocitaci, spravte RANDOMIZE X, kde X je adresa vasich piatich bajtov a potom PRINT USR Y, kde Y je zaciatocna adresa tohto programu. A vypise sa vam vasa tuzobne ocakavana hodnota cisla.
     Na tomto mieste asi mnohi namietnu, ze funkcia USR predsa vracia obsah registra BC (t.j. cele cislo 0-65535) a teda nemoze vratit lubovolne realne s plavajucou desatinnou ciarkou ! Tak pre tych iba tolko: Niekedy sa deju aj zazraky a dalej bude vysvetlene, ako je to mozne.
     Ak by ste sa nahodou chceli pozriet, ake cislo sa nachadza na adrese 0, tak namiesto RANDOMIZE 0 spravte POKE 23760,0: POKE 23761,0 (to preto, lebo RANDOMIZE pri nulovom alebo ziadnom argumente berie nahodne cislo z premennej FRAMES).
     Ako tento program pracuje ? Hned na zaciatku vidite POP HL. Dost neobvykly zaciatok, poviete si. Ale tento program vyuziva istu fintu so zasobnikom. Totiz pri volani USR prva navratova adresa na zasobniku procesora ukazuje na rutinku #2D2B, ktora uklada hodnotu registra BC na zasobnik kalkulacky vo forme piatich bajtov. A prave tato rutinka je teraz pre nas neziaduca, preto je jej adresa zlikvidovana pomocou toho POPu.
     Lenze pri navrate z USR by sa patrilo nieco dat na zasobnik kalkulacky. A preco by sme tam nedali tych nasich pet bajtov, o ktore nam prave ide ? A prave ina rutinka na adrese #33B4 robi takuto cinnost. Takze ju uz len staci zavolat s tym ze v registri HL je adresa odkial sa ma zobrat tychto pet bajtov.
     Register HL sa naplna hodnotou ulozenou na adrese 23670. Je to premenna SEED, ktora sa nastavuje pomocou prikazu 0RANDOMIZE. Samozrejme by sa dalo v nasom programe namiesto LD HL,(23670) napisat LD HL,XXX a hodnotu XXX priamo pokovat, ale sposob s vyuzitim RANDOMIZE sa mi vidi predsa len praktickejsi.
     Verim, ze ak vas tento program nezaujal tym ze zistuje hodnoty cisel, aspon vam priniesol nieco nove v tom, ako zariadit aby funkcia USR vracala lubovolnu realnu hodnotu.

Vas Busy.

Nazad / back