Skip to main content
© Dyno

 "Internet is so huge and pointless that for some people it is  a
complete substitute for life."


                YOUR SECOND GFA BASIC 3.XX MANUAL
                             - or -
        HOW I LEARNED TO STOP WORRYING AND LOVE GFA-BASIC
                             PART 19
                CHAPTER EIGHTEEN - PROGRAM LOOPS
                          by Han Kempen

Calculations

 Try to remove all unnecessary calculations from loops, e.g.:

     FOR i=1 TO 1000
       x(i)=2*q*i
     NEXT i

 It's a better idea to calculate 2*q outside the loop:

     q2=q*2
     FOR i=1 TO 1000
       x(i)=q2*i
     NEXT i

 Always  try  to  convert floating point  variables  to  integers
before  entering a loop.  Then you will be able to use  the  fast
integer-operators. An obvious example would be a calculation with
dollars  (24.37)  that could be replaced by  a  calculation  with
cents  (2437).  Use this method if you know the  lowest  possible
value of the floating point variable (0.01 in this case) and then
divide  by  this value.  But watch out for  rounding  errors  and
integer-overflow.

 Powers of 2 can be calculated fast by setting a bit:

     x%=BSET(0,6)   ! faster than x%=2^6

 And for the ultimate speed-freaks, multiplying with a power of 2
is slightly faster with SHL:

     y%=SHL(x%,3)   ! faster than y%=MUL(x%,8)

 Of course there is no overflow-control if you use SHL (or MUL).

 Sometimes,  calculations in a loop can be replaced by a  look-up
table:

     FOR i=1 TO 1000
       y%(i)=x|(i)^2
     NEXT i

 First, create a table of squares:

     DIM square%(255)
     FOR i=0 TO 255
       square%(i)=i*i
     NEXT i

 Then use this table in the loop:

     FOR i=1 TO 1000
       y%(i)=square%(x|(i))
     NEXT i

FOR ... NEXT

 I  use  local variables in Procedures if possible.  But  if  you
intend  to  compile  the program later,  you  could  declare  the
counter  in  a FOR ...  NEXT loop as a global  variable.  In  the
compiled program,  the loop will be executed slightly faster. The
gain in speed is almost negligible,  so this is not a good reason
to use global variables instead of local variables.

 If you use floating point count-variables in a FOR ... NEXT loop
(or any other loop), you could encounter unexpected problems:

     FOR i#=0.1 TO 0.9 STEP 0.1
       PRINT i#
     NEXT i#

 You  would expect 0.9 as the result of the last addition (0.8  +
0.1),  but 0.9 is never printed!  This is not a bug in GFA-Basic,
but  caused by the internal (binary) representation  of  floating
point  numbers.  The last addition results in a  number  slightly
larger  than  0.9 and therefore the loop is left  after  printing
0.8 . If you insert the line

       i#=ROUND(i#,14)

in the loop, you can solve this problem. But the best solution is
to avoid floating point count-variables in loops.  Integer count-
variables are much faster. You could easily change the loop into:

     FOR i&=1 TO 9
       PRINT USING "#.#";i&/10
     NEXT i&

 If you use a floating point variable in a REPEAT ... UNTIL loop,
you  can avoid the rounding error by using the  special  operator
'==', which compares the first 28 bits (roughly 8 decimals):

     i#=0
     REPEAT
       i#=i#+0.1
       PRINT i#
     UNTIL i#==0.9

 But you can't use the '=='-operator in a FOR ... NEXT loop.

 In  the following three examples a byte-variable is used as  the
counter:

     FOR i|=5 DOWNTO -1
       PRINT i|
     NEXT i|
     '
     FOR i|=250 TO 256
       PRINT i|
     NEXT i|
     '
     FOR i|=255 DOWNTO 0
       PRINT i|
     NEXT i|

 Of course, a byte-variable cannot have a value of -1 or 256. GFA
does  not abort with an error-message,  but skips the  first  two
loops.  Not  a true bug perhaps,  but close.  The third  case  is
different,  there  we enter an endless loop.  That's because  the
counter becomes -1 after the last step,  and that is seen as  255
through  the  byte-spectacles of the loop so we  start  all  over
again. You should realize that the FOR ... NEXT counter is always
increased/decreased (with TO/DOWNTO) with one before leaving  the
loop:

     FOR i&=1 TO 100
       ' Never mind this line
     NEXT i&
     PRINT i&                      ! i& is now 101, not 100

 If  the user should be able toa bort a long FOR  ...  NEXT  loop
prematurely, you could use EXIT IF:

     FOR i%=1 TO 100000
       (...)
       EXIT IF INKEY$=CHR$(27)     ! user pressed <Esc>
     NEXT i%

Loops

 Although  you  can use many different loops  in  GFA-Basic  3.0,
there  are  basically only two varieties.  You can first  test  a
condition, and then either continue or leave the loop. Or you can
first enter the loop,  and then test a condition to decide if you
are going to continue or leave.

 In  an interpreted program the first choice is the fast FOR  ...
NEXT loop,  then the (slower) REPEAT ...  UNTIL loop and  finally
the  (slowest) WHILE ...  WEND loop.  In a compiled  program  all
loops are executed equally fast!  If you use a DO  ...  LOOP,  an
EXIT IF condition will always take some extra time.

 Try  to avoid a negative test in a loop,  as it will  take  more
time to evaluate this. E.g. replace:

     WHILE NOT condition!
       (...)
     WEND

 by the much faster:

     DO UNTIL condition!
       (...)
     LOOP

 Or similarly replace:

     REPEAT
       (...)
     UNTIL NOT condition!

 by the faster:

     DO
       (...)
     LOOP WHILE condition!

 Finally,  you  could  combine the test of one condition  at  the
start  of the loop with the test of another condition at the  end
of the loop:

     DO UNTIL condition_1!
       (...)
     LOOP WHILE condition_2! 

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.