50. Rýchle celé čísla: --int a REM @FLOAT

Na čo to je

Každé číslo je v Atari BASICu aj v Turbo-BASICu XL šesť bajtov v desiatkovej sústave (kapitola 4). Vďaka tomu 1/3 vyjde na desať trojok – ale aj I=I+1 znamená sčítanie desiatkových čísel po bajtoch, a to je na procesore 6502 pomalé.

Väčšina programov však počíta len s celými číslami: počítadlá slučiek, súradnice, adresy, body v hre. Voľba --int povie prekladaču, že číslo je celé číslo v štyroch bajtoch, tak ako ho počíta procesor. Program je potom dva- až trikrát rýchlejší, ak počíta, a o kúsok menší. Pôvodný interpreter nič také nemá – je to rozšírenie prekladača.

Kde program desatinné čísla naozaj potrebuje, povie riadok REM @FLOAT, ktoré premenné ich majú držať.

Ako sa to zapne

Voľbou --int, najlepšie v hlavičke programu (kapitola 40):

Turbo Basic XL
0 REM @COMPILE --int

Bez nej je všetko po starom.

Ako počíta

ČoS --int
číslocelé, od −2 147 483 648 po 2 147 483 647
výsledok mimo tohto rozsahu (+ - *, /, READ, INPUT, VAL)chyba 11
/delí celé čísla a zlomok zahodí smerom k nule: 7/2 je 3, -7/2 je −3
delenie nulouchyba 11
adresa pre PEEK, POKE, MOVE …, index poľa, GRAPHICS0 až 65 535, inak chyba 3 ako v BASICu
POKE s hodnotou mimo 0–255, DPOKE mimo 0–65 535chyba 3
FOR I=1 TO 2147483647slučka ako každá iná; NEXT za najväčším číslom skončí bez chyby
READ, INPUT, VAL s desatinným číslomzlomok sa zahodí (1.9 je 1)
&, !, EXOR (Turbo-BASIC XL)na všetkých 32 bitoch, aj záporné čísla
MOD, DIV (Turbo-BASIC XL)DIV je /, MOD je zvyšok so znamienkom delenca
premennáosem bajtov v tabuľke premenných ako vždy
prvok poľaštyri bajty namiesto šiestich

Čísla napísané v programe sa počítajú pri preklade presne: 320*160/8 je 6400. Číslo, ktoré sa do 32 bitov nezmestí, je chyba už pri preklade.

Desatinné čísla vo výpočte

Výraz s desatinným číslom (0.5, 2.0, 1E3), so SIN, COS, ATN, SQR, LOG, CLOG, EXP, RND alebo ^ sa počíta po starom, v šiestich bajtoch, a až výsledok sa zmení na celé číslo – zlomok sa zahodí smerom k nule. X=INT(100*RND(0)) tak funguje ako vždy. INT, TRUNC, FRAC, ABS a SGN desatinného čísla dajú desatinné číslo (INT(-1.5) je −2), porovnanie a AND, OR, NOT dajú 1 alebo 0. PRINT desatinného výrazu vypíše desatinné číslo.

Do celej premennej sa však zlomok neuloží: X=0.5 je chyba, STEP so zlomkom pri celej premennej tiež.

REM @FLOAT: premenné so zlomkom

Premenné a polia, ktoré majú držať desatinné čísla, vymenuje riadok REM @FLOAT na začiatku programu, pole s otvorenou zátvorkou:

Turbo Basic XL
0 REM @COMPILE --int
1 REM @FLOAT X,Y,A(

Taká premenná má šesť bajtov a počíta sa s ňou ako v BASICu – aj FOR s STEP 0.25. Pole má šesť bajtov na prvok. Celé číslo sa do nej uloží presne, jej hodnota v celej premennej stratí zlomok. Riadkov REM @FLOAT môže byť viac, platia len tie pred prvým príkazom programu. Reťazec v nich byť nemôže.

Pozor na delenie: Y=X/2, keď je X celé, delí celé čísla, aj keď je Y vo @FLOAT. Kto chce zlomok, napíše X/2.0.

Celý program

Súčet štvorcov, delenie, plocha kruhu a číslo, ktoré sa už nezmestí.

Súbor examples/whole.abas:

Atari BASIC
0 REM @COMPILE --int
1 REM @FLOAT R,P
10 REM Whole numbers in four bytes, two variables with a fraction
20 S=0:FOR I=1 TO 1000:S=S+I*I:NEXT I
30 PRINT "SUM OF SQUARES: ";S
40 PRINT "7/2 = ";7/2;", -7/2 = ";-7/2
50 R=10:P=3.14159265*R*R
60 PRINT "CIRCLE AREA: ";P
70 PRINT "WHOLE PART: ";INT(P)
80 X=2147483647:PRINT "LARGEST: ";X
90 TRAP 120:X=X+1
100 PRINT "NEVER HERE"
110 END
120 PRINT "ERROR ";PEEK(195);": IT DID NOT FIT"

Preklad a spustenie

Basic26 whole.abas --sim

Čo uvidíš

SUM OF SQUARES: 333833500
7/2 = 3, -7/2 = -3
CIRCLE AREA: 314.159265
WHOLE PART: 314
LARGEST: 2147483647
ERROR 11: IT DID NOT FIT

Ten istý program bez --int (Basic26 whole.abas --sim --no-source-options) vypíše 7/2 = 3.5, ako najväčšie číslo 2147483640 – v šiestich bajtoch BASIC z napísaného čísla prečíta len deväť číslic – a NEVER HERE, lebo o jednotku väčšie číslo sa do šiestich bajtov ešte zmestí.

Ako to funguje

Ako rýchlo

Čas v sekundách v emulátore (PAL), ten istý program preložený bez voľby a s --int:

ProgramBez --int--int
500× PRINT10,2610,18
X=X+1 v slučke1,761,24
B*2, (C-B)/211,645,28
sito prvočísel v reťazci54,5420,14
POKE do obrazovky8,123,78
práca s reťazcami21,9213,34
náhodné bajty do GRAPHICS 84,642,98
bublinkové triedenie8,15,8
posun hráča cez PEEK a POKE15,105,94

Čím viac program počíta, tým viac získa. Výpis textu sa nezrýchli – čas tam ide do operačného systému. Prekladač FastBASIC, ktorý celými číslami počíta vždy, zvládne bajty do GRAPHICS 8 za 2,34 s a triedenie za 6,58 s.

Časté chyby

Čo sa stanePrečo
error B26011: with --int, 0.5 is no whole number of 32 bits; add X to REM @FLOATdo celej premennej ide zlomok – pridaj ju do REM @FLOAT
error B26011: with --int, a STEP with a fraction needs a floating point loop variable (REM @FLOAT)FOR so STEP 0.25 potrebuje premennú vo @FLOAT
error B26011: 2147483648 does not fit in 32 bitsčíslo v programe je väčšie než štyri bajty
warning B26233: with --int, / leaves no fraction for the * to multiply …A/B*C stratí zlomok skôr, než sa násobí; C*A/B nie
warning B26233: with --int this asks whether N divides X …X/N=INT(X/N) je v starých programoch otázka „delí N číslo X?“ – prekladač to tak preloží; jasnejšie je X MOD N=0 v Turbo-BASICu XL, X-X/N*N=0 v Atari BASICu
warning B26233: with --int, X=RND(...) is always 0 …RND je zlomok; do celej premennej INT(N*RND(0))
error B26042: REM @FLOAT A$: a string is not a numberreťazec do @FLOAT nepatrí
ERROR- 11 za behuvýsledok sa nezmestil do štyroch bajtov, alebo delenie nulou
program počíta inak než bez --intniekde delí celé čísla a zlomok čakal; premennú daj do @FLOAT alebo pridaj .0

Vyskúšaj si

  1. Zmeň riadok 40 na 7/2.0. Čo vypíše?
  2. Vyhoď z riadku 1 premennú P. Čo povie prekladač?
  3. Prelož svoj program z kapitoly 10 s --int a bez neho a porovnaj, čo vypíšu.

Zhrnutie

Tu sa kniha končí. V prílohách nájdeš všetko ešte raz v tabuľkách – a v priečinku examples pri prekladači stovky programov, na ktorých si to môžeš vyskúšať.

Späť: 49. Hráči a strely · Ďalej: A. Jazyk na jednej strane