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):
0 REM @COMPILE --int
Bez nej je všetko po starom.
Ako počíta
| Čo | S --int |
|---|---|
| číslo | celé, 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 nulou | chyba 11 |
adresa pre PEEK, POKE, MOVE …, index poľa, GRAPHICS | 0 až 65 535, inak chyba 3 ako v BASICu |
POKE s hodnotou mimo 0–255, DPOKE mimo 0–65 535 | chyba 3 |
FOR I=1 TO 2147483647 | slučka ako každá iná; NEXT za najväčším číslom skončí bez chyby |
READ, INPUT, VAL s desatinným číslom | zlomok 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:
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:
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 FITTen 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
- Riadok 0 zapne
--int, riadok 1 dá premennýmRaPdesatinné čísla. - Riadok 20 počíta len s celými číslami – tu je
--intnajrýchlejší. - Riadok 40:
/medzi celými číslami zahodí zlomok smerom k nule. - Riadky 50–70:
Pje vo@FLOAT, takže si plochu pamätá aj so zlomkom;INT(P)je celá časť. - Riadky 80–90: 2 147 483 647 je najväčšie číslo v štyroch bajtoch, o jednotku viac je chyba 11, ktorú zachytí
TRAP.
Ako rýchlo
Čas v sekundách v emulátore (PAL), ten istý program preložený bez voľby a s --int:
| Program | Bez --int | --int |
|---|---|---|
500× PRINT | 10,26 | 10,18 |
X=X+1 v slučke | 1,76 | 1,24 |
B*2, (C-B)/2 | 11,64 | 5,28 |
| sito prvočísel v reťazci | 54,54 | 20,14 |
POKE do obrazovky | 8,12 | 3,78 |
| práca s reťazcami | 21,92 | 13,34 |
| náhodné bajty do GRAPHICS 8 | 4,64 | 2,98 |
| bublinkové triedenie | 8,1 | 5,8 |
posun hráča cez PEEK a POKE | 15,10 | 5,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 stane | Prečo |
|---|---|
error B26011: with --int, 0.5 is no whole number of 32 bits; add X to REM @FLOAT | do 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 number | reťazec do @FLOAT nepatrí |
ERROR- 11 za behu | výsledok sa nezmestil do štyroch bajtov, alebo delenie nulou |
program počíta inak než bez --int | niekde delí celé čísla a zlomok čakal; premennú daj do @FLOAT alebo pridaj .0 |
Vyskúšaj si
- Zmeň riadok 40 na
7/2.0. Čo vypíše? - Vyhoď z riadku 1 premennú
P. Čo povie prekladač? - Prelož svoj program z kapitoly 10 s
--inta bez neho a porovnaj, čo vypíšu.
Zhrnutie
--int: číslo je celé, v štyroch bajtoch, od −2 147 483 648 po 2 147 483 647; čo sa nezmestí, je chyba 11./zahodí zlomok smerom k nule.- Desatinné čísla vo výraze fungujú, výsledok sa zmení na celé číslo.
REM @FLOAT X,Y,A(dá vymenovaným premenným a poliam desatinné čísla.- Program, ktorý veľa počíta, je dva- až trikrát rýchlejší.
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