Classic Computer Magazine Archive CREATIVE COMPUTING VOL. 10, NO. 2 / FEBRUARY 1984 / PAGE 210

Notebook - portable computing. (Basic and TRS-80 Model 100 computer) (column) Bill Machrone.

Basic is the heart of your Model 100, in more ways than one. First, it is an easy-to-learn language with great power for calculation, screen display, file handling and more. Second, the facilities coded into Basic are shared by other programs in the ROM. Here you will learn how to maximize the power and speed of Basic and use many of its features more effectively, through the examples provided. Loops

Looping (repeatedly performing a task) is the single most powerful and useful task a computer can do. Unlike us, a computer never gets bored. We, however, occasionally get bored waiting for the computer to finish its calculations. Therefore, you should do everything in your power to make loops run as fast as possible. Below are several ways to "get the lead out." Try this on your machine:

10 TIMES$ = "00:00:00"

20 FOR X = 1 TO 10000

30 NEXT X

40 PRINT TIMES

That's right, we are just asking the machine to count to ten thousand, and using the built-in clock to time it: Run the program, and you will find that it takes about 30 seconds to execute. That is much faster than you or I could count to ten thousand, but not as fast as it could be. Add this line to your programs and run it again!

5 DEFINT X

The execution time drops to about 10 seconds. What's the difference? Basic automatically assumes that all numbers are floating-point or double precision numbers. That means that all calculations are carried out to 14 places and can have a range of 10.sup.6.sup.2 to 10.sup.-.sup.4.sup.4. That is a lot of overhead for just counting from 1 to 10,000 or in other situations in which you don't need decimal places.

The 80C85 microprocessor inside your Model 100 can handle integer addition at least three times faster than floating point. DEFINT DEFines INTegers. We declared X to be an integer, which in the case of Basic, means that it is a whole number (no decimal places) between -32768 and +32767. You can count only up to 32767 if you start at one, but if you need a larger fast loop, you can start at negative values all the way down to -32768 and thus extent your fast looping range to over 65000.

If, in the extreme case, you need to do something more than 65000 times, it is still faster to nest two integer loops (put one inside the other) than to use a floating point number to control the loop.

There is another level of numeric precision available, single precision. While it does floating point arithmetic too, it uses less space for the numbers, as it stores them in the Model 100 memory. It also has a numeric range of 10.sup.6.sup.2 to 10.sup.-.sup.6.sup.4., but it is only marginally faster than double precision in our example, completing the count in about 27 seconds.

There is another way to speed up our routine. Basic is an interpretive language, meaning that it must read and evaluate (understand) each character that you type. Some of its operations are implicit, meaning that it will do the right thing whether you have the "right" thing in your program or not.

A perfect case in point is the NEXT statement in FOR-NEXT loop. You can speed up the program dramatically by simply eliminating the X in line 30:

10 TIMES$ = "00:00:00"

20 FOR X = 1 TO 10000

30 NEXT

40 PRINT TIMES

For an integer loop, the execution time drops to 6 seconds, a 40% improvement! Why should one character make so much difference? It is all in the way Basic does things.

First, when you say FOR X = 1 to 10000, Basic sets up a counter in memory. NEXT is the trigger that tells it to add one more to the counter and check to see if it has satisfied the requirement by having completed the count. When you have an X (or any variable name) on the NEXT line, it calls in another routine whic simply locates variables by name in memory. Easy enough, but when you do it 10,000 times, the overhead adds up.

You can shorten the execution of FOR-NEXT loops on any version of Microsoft Basic with this technique but the speedup is more dramatic on the Model 100 than most. We mentioned nested loops briefly above. Let's look at an example:

10 DEFINT X,Y

20 FOR X = 1 TO 100

30 FOR Y = 1 TO 100

40 NEXT

50 NEXT

When you run this program, you will find that it takes only a second longer to count to 10,000 with two loops. Using NEXT X and NEXT Y costs the same four second penalty that it did above. Note the indented structure of the program. This is done to keep things clear in terms of what happens when.

While indented structure is relatively unimportant in short examples like this, it is a very good habit to get into. In a normal progam there would probably be many lines between the FOR and NEXT statements. Keeping them indented keeps you organized.

But, you may ask, if Basic has to parse (examine) every character on each line, don't those extra spaces slow the program down? Well, yes and no. They do, but not by much. Take the two examples below:

10 DEFINT X,Y

15 TIES = "00:00:00"

20 FOR X = 1 TO 1000

30 FOR Y = 1 TO 100

40 NEXT

50 NEXT

60 PRINT NAMES

10 DEFINT X,Y

15 TIMES="00:00:00"

20 FOR X=1TO1000

30 FORY=1TO100

40 NEXT

50 NEXT

60 PRINTTIMES

Which would you rather debug? This double loop is slightly different from the one presented earlier; the outside or X loop counts to 1000 instead of 100. The top one takes 1:17 to complete and the bottom takes 1:14. do you have three seconds to spare next time you have to do something a hundred thousand times? The bottom line is that your program might as well be readable, because the impact on their performance will be neglible.

By the way, use a tab instead of a bunch of spaces when you indent.

It represents only character that Basic has to parse instead of multiple spaces, but it looks like eight spaces on the screen.

There is no faster way than a FOR-NEXT loop to control things in Basic. For instance, the following code

10 DEFINT X

20 X = 10000

30 X = X - 1

40 IF X > 0 THEN GOTO 30 takes more than a minute to execute. Substraction or counting down, by the way, is a few seconds faster than addition or counting up.

Suppose you want to avail yourself of the fastest looping available but don't know how many times you will have to go through the loop to get the result you want?

This can be the case in iterative problem solving, as in solving an equation or in string searches. For example, you can use Basic to search a file for a specific character. Normally, you would do this with a WHILE loop, a feature not available in Model 100 Basic.

The alternative is to set a TO value greater than the number of times you are likely to need to go through the loop. When you find the value of whatever you are looking for, set the loop variable to the control variable. That way, the loop ends "naturally," instead of being interrupted.

Basic can then perform "garbage collection" on the "used" variables and re-use them elsewhere. Besides, it is always good form to have a single exit point from a routine, avoiding "spaghetti code."

Looping until z is found in a file: Good Example:

10 FOR LOOP = 1 TO 32767

20 TEST$ = INPUT$(1,1)

30 IF TEST$ = "z" THEN LOOP = 32767

40 NEXT

50 Program continues Bad Example:

10 FOR LOOP = 1 TO 32767

20 TEST$ = INPUT$(1,1)

30 IF TEST$ = "z" THEN 50

40 NEXT

50 'Program continues

In the second example, the loop is never satisfied. In fact, if another NEXT is encountered in the program (without an intervening FOR statement); the loop will begin executing where it left off. Don't get any ideas about how you can use this "feature." It is not the way to do things.