CHAPTER ONE: INTRODUCTION

©1982, John E. Miller

This means you can read it but not save soft copies or publish in any form or re-distribute without my permission. Thanks, John


The History section traces the development of programming and operating systems.

The BASIC Commands section introduces a working set of BASIC commands: NEW, DEL, LIST, RUN, SAVE, OLD, RENAME, and BYE.

The BASIC Statements section introduces eight simplified BASIC statements: INPUT, LET, PRINT, GOTO, IF, FOR, NEXT, and END. This will be sufficient to write programs in Chapters Two, Three, and Four. The eight statements are then covered in detail in Chapters Five and Six.

The BASIC Syntax section shows how what was described by specific examples in the BASIC command and statement sections can be summarized graphically. These type of diagrams are then used throughout the book to describe the form of BASIC expressions and statements.

History

The history of computation goes back at least to the Babylonians. The history of mechanical computation started, however, in 1642 with a young man, Blaise Pascal (Figure 1-1), who invented the first adding machine (Figure 1-2) to relieve the burden of computation of his father's accounting work.

Before the year 1800, children were employed in textile mill weaving processes to monotonously push levers which lifted combinations of threads to form patterns in the fabric. In 1804 Joseph Marie Jacquard (Figure 1-3), once himself a drawboy, invented an automatic loom (Figure 1-4) that wove patterns according to a series of prepared cards strung together on a belted conveyance. The loom could read each card by mechanically sensing the presence of a hole or no-hole corresponding to each warp thread. The selected threads would be raised and the shuttle run across. Then the next card on the belt was positioned, etc. This way, complex patterns could be mass produced without assistance. The operator merely selected the pattern and set up the loom. This is now considered a significant step in the development of automatically controlled calculation.

Around 1822, an Englishman, Charles Babbage worked fanatically to build his 'analytical engine', a machine that could perform sequences of operations under automatic (programmed) control like the Jacquard loom. His design included a 'store' for holding both the data and intermediate results of computations, and a 'mill', for performing the instructions as read from the cards. Babbage's cohort, Ada Augusta (Figure 1-5) helped by deducing that his machine would need not only arithmetic operations, but also an instruction that could skip over succeeding instructions or go back to a preceding instruction according to the negative, zero, or positive result of the last operation performed. Babbage never succeeded in building his engine, however, due to lack of funding and his inability to freeze the design (Figure 1-6) so that his millwright could go to work. Rather, he pursued design after design for each component of the machine, seeking simplicity. After his death, his son and Munro Company constructed a working model from his plans.

Babbage's original motivation was to improve the accuracy of tables of logarithms. World War II intensified the demand for performing complex mathematical calculations for preparing ballistics tables. Several groups worked to design a machine that could store the instructions in the same memory as was used previously only for data. This design idea is referred to as the 'stored program' concept. (It is not clear that any one person should receive credit for this concept). Memory was designed to consist of a series of numbered locations or 'addresses', so that the machine could progress from one to the next for its instructions just as the Jacquard loom read pattern cards. As Ada Augusta had written, the program could choose to skip over certain instructions, or go back and repeat a set of instructions based on some condition that arose during the actual computation. The first stored program machine, EDSAC, became operational in 1949 at Cambridge University in England.

A program consisted of a list of numbers to be stored in the machine's memory in contiguous (sequential) locations. The machine would interpret part of the number as an 'operation code' and the other part as an 'operand'. An operand would be either an 'address' of data to be used in the operation, or the data itself. For example, operation code #1 might mean to add the contents of a specified memory cell to the totalling register; operation code #2 might mean to store the contents of the totalling register in a specified memory cell. Operation code #3 might be to load the totalling register with a particular number contained in the second half of the instruction. A program, then, would look something like:


OPCODE | OPERAND
-------|---------
  3    |  0
  1    |  1728
  1    |  1729
  2    |  1730

The above hypothetical program zeros the accumulating register, adds the numbers in memory locations 1728 and 1729 into it, and then stores the result in memory location 1730. Each of the early designs had its own way of doing this, a different set of operation codes, a different way of addressing memory. The name given to this program specification/coding scheme was 'machine language'.

Machine language programs were very tedious to prepare and even worse to modify. Therefore, A program was written with 'mnemonic' (memory aiding) codes rather than numeric operation codes and addresses. Each operation code had a unique mnemonic, and each memory location was given a symbolic name (like "A" or "Q"). The above machine language program might have looked like the following on some engineer's note pad in 1949:


MNEMONIC | SYMBOLIC
 OP CODE | OPERAND
---------|---------
     ZAP |
     ADD | A
     ADD | B
     STO | C

These symbolic programs were turned over to clerks whose job it was to assemble a machine language program and to load it into the memory of the computer by flipping an absurd number of switches, etc. This clerical process was soon seen to be mechanical in its own way. Thus, the first significant development in programming languages was the invention of programs for the translation from assembly (symbolic) language to machine language. This meant that the clerical translation could be done by the computer itself. Since the computer could store numbers into its own memory, it could also load the program! This was a revolutionary idea. A program that reads assembly language instructions and produces machine language instructions for a particular computer is yet today called an 'assembler'.

While assembly language programming was a great improvement over machine language, a programmer was still spending more time writing instructions for the computer than solving the problem at hand; the little program above simply makes C take on the value of A plus B. In practice, a programmer would first write an expression algebraically (C=A+B), then write a sequence of assembly instructions to perform the required operations. A hierarchy of programmers was formed, the upper level programmers were mathematicians writing algebraic expressions, while the lower level workers wrote the corresponding assembly programs. (A person who did such translations was called a 'compiler'). The assembly language written by the compilers could then be assembled by the computer. As before, it was soon realized that the translation from an algebraic expression to assembly instructions, no matter how complex, was mechanical. A program was written that could read an algebraic expression as its input and produce the sequence of assembly instructions required to evaluate the expression as its output. People no longer needed to compile programs. This new type of translating program became known as a 'compiler'.

While an assembler produces only one machine language instruction for each assembly instruction, a compiler will produce several instructions for each expression in the original 'source program'. This many-to-one translation was extended to include 'statements' for inputting and printing data, as well as for altering the sequential execution of the program. The important idea is that the effect of the machine language program, when executed, is the same as the effect expected by the higher-level language programmer.

A goal of the pioneers in this area was that, for each kind of computer, a compiler could be written that would translate a general language into that machine's language. It was hoped that the same high-level program could be used on any machine with the same results. The degree to which this goal has been realized is beyond the scope of this story, but it continues to be a driving force in language design today.

The next significant development does not relate directly to language development, but to the general operation of a computer 'system'. Consider the steps originally necessary to develop a program. Each statement of the program was punched onto a hollerith card. The compiler program, which was also stored on cards or paper tape in machine language form, was loaded into the computer's memory followed by the program to be compiled. If the compiler discovered typographic errors (mismatched parentheses, misspelled keywords, etc.) it would reject the source program and not produce the 'object program' (machine language). The source program would be corrected and the compiler re-loaded for another try. If the compilation was successful, the object program would be punched onto cards or paper tape; then the operator would load the object program for testing, which would disclose various errors in either the computation technique, or the displaying of the results. This entire process would be laboriously repeated until the program was 'debugged'. The compiler deck or tape was literally worn out due to its incessant reuse.

A development in computer hardware presented a solution to this madness. A new medium, magnetic disks and tapes, provided a residence for frequently-used programs as well as for data. A compiler could be summoned from the rapidly spinning disk whenever needed, and as frequently as needed without concern for wearing it out. The object program could be stored on the disk temporarily until testing was completed, then it could be punched out for 'off-line' storage. Other useful programs and small data files were stored on disks and tapes. Thus, the first program 'libraries' were formed. To help in controlling the computer, yet another program was written solely for the purpose of accepting commands from the operator and fetching a particular 'system program' for use. Such programs were given names like 'monitor', 'supervisor', or 'host operating system'. All library programs ran from the system relinquished control of the computer to the supervisory program when they completed their task.

The primary input device of the day was a card reader. A job consisted of a deck of cards containing sequences of commands, programs, and/or data representing one user's request. The system would do one job, then go on to the next deck of cards in the card reader. Such systems are called 'batch' systems.

As disk technology improved, the capacities of disk drives grew. Operating systems were expanded to provide librarian service for storing object programs on disks and tapes. This made the work of developing programs and systems of programs much easier in addition to increasing the potential workload of operational systems.

In time, the speed of newer generation computers became so great that the computer sat idle a great portion of the time while it waited for its input and output devices, which are limited by mechanical inertia. To make use of this time and to make the computer directly available to a greater number of users, the design of computers was extended to allow for 'partitioning' of its memory so that it could work on several programs concurrently (not simultaneously). Each user would communicate via a 'terminal' having a 'keyboard' and 'display'. The operating system became a 'timesharing' system, meaning that the supervisor would give each process a tiny 'slice' of time say one-hundreth of a second. Since the computer could do tens of thousands of instructions during that time, each user has the illusion that the computer is working solely for them, while in fact it is handling all of their requests. The performance of the system as a whole is maintained by a priority system which prevents any user from hogging time. If a request is made for more computation that can be completed in one slice, the work is spread out over a number of slices. The 'response time' will become greater if many users all make substantial requests, overloading the system. Otherwise, individuals are not aware that they are sharing the computing resource.

One of the pioneering institutions in timesharing was Dartmouth College. There, BASIC (Beginner's All-purpose Symbolic Instruction Code) was designed to take advantage of this new user-machine relationship by providing an interactive way to write and test programs. With it, a programmer can experiment with increasingly complex versions of a program. BASIC provides a line-by-line program 'editor' so that a programmer can easily change any statement in the program at any time. The BASIC editor checks each statement for grammatic correctness. This way, the programmer gets immediate feedback, rather than having to wait till run-time to find out that some trivial typographic error was made.

BASIC is intentionally simple so that students and teachers can learn the fundamentals of programming without being bogged down by the details of more a sophisticated language.

Another innovation of BASIC is that it does not translate a program into machine language, but rather 'interprets' its source code directly. When BASIC interprets LET C=A+B, the current value of "A" is added with the current value of "B" and the result is stored in "C". This is the effect that we expect without generating machine language instructions for the computer to execute. BASIC can begin interpreting a program immediately upon request, whereas a program in another language may need several seconds or minutes to be compiled before execution. A program written in an interpreted language will run slower than the same program written in a compiled language. An interpreter is a computer program itself which stands between the machine and the program, whereas a compiled program is executed directly by the circuitry of the machine. But BASIC programs tend to be smaller and do simpler computations than industrial or commercial application programs. BASIC was invented primarily for students, who change their program many times before getting it correct. In such an environment, interpretation is less time-expensive than compilation.

BASIC handles the fetching and storing of source programs so that a user does not have to learn the in's and out's of a 'host' operating system. In this sense, BASIC is a sub-operating system which is somewhat standard from one machine to the next.

In the 70's, the micro-electronic revolution reduced the cost of a computer to a level that each user could have a personal computer. Although BASIC was designed in a time-sharing environment, it was also a good candidate for a programming language for the micro-computer, because of its simplicity. BASIC is now used both on large time-share systems and on home computers.

Summary: If necessity was ever the mother of invention, programming languages are surely among her children. The evolution of programming and operating systems has been one of shedding the burden of tedious human tasks.

BASIC Commands

Before using BASIC on a time-sharing system you must identify yourself and enter your assigned password. If you have a personal computer, you simply need to turn it on and load the supervisory program. Each host operating system has a way to specify that you want to use the BASIC subsystem, usually typing "BASIC" followed by the RETURN or ENTER key. Once under control of BASIC (referred to as "Being in BASIC"), you will be aware of two distinct states or modes. One state is for creating a program, the other is for running a program. When you first get into BASIC, your 'workspace' is empty. (The workspace is an area of the computer's memory reserved for the text of one source program). The first thing you will do is to tell BASIC whether you wish to create a new program or to recall a previously written one. To create a new program, type "NEW", followed by the name that you wish to give the program, for example:


NEW adder

Every command you give is followed by the RETURN key. BASIC does nothing till the RETURN key is depressed. This allows you to rub out a typographic error on the line you are entering before hitting RETURN.

A new program is entered into the workspace by typing it line by line. Each line must have a line number that gives its placement in the program. A programmer usually starts a BASIC program with line 10 or 100, and numbers the lines of the program by 10's:


10 REM  This program adds two numbers
20 INPUT A,B
30 LET C = A + B
40 PRINT C
50 END

Leaving unused line-numbers allows afterthoughts, omissions, and changes to be inserted between previously entered lines:


35 PRINT "The sum is:"

This presents a potential hazard. If you accidentally type the wrong line-number, the statement entered may overlay some other statement or be inserted at the wrong place in the program. No warning can be given, since this is BASIC's way of letting you change your program. You are the boss. It will obey you blindly, so be careful!

Similarly, a line may be deleted by simply typing just the line number itself, or by explicitly typing "DEL" followed on the same line with the line number of the line to be deleted:


DEL 35

A segment of the workspace may be deleted. For example, "DEL 10-30" deletes lines 10 through 30, however many lines that may be. A line may be corrected or changed by simply retyping it, and BASIC will see to it that the new line overlays the old.

The contents of the workspace may be reviewed at any time with the LIST command. "LIST", followed by the RETURN key, will list all the lines of the workspace. The list may be limited to a portion of the program by saying "LIST m-n", where m and n are the first and last lines to be listed. Many systems put the date and the time on the listing. This dates a particular listing generated on a printing terminal so that successive listings may be arranged in the order they were made.


LIST
ADDER     13-SEP-1981   4:21

10 REM  This program adds two numbers
20 INPUT A,B
30 LET C = A + B
40 PRINT C
50 END

Ready

To have the program interpreted you type "RUN" and watch what happens:


ADDER     12-DEC-1981   5:52

?

BASIC displays its characteristic time-date-workspace-name heading and the program commences. The INPUT statement on line 20 causes the "?" to appear. Now, you enter two numbers and hit RETURN:


? 2,2
 4

Ready

The INPUT Statement accepted two numbers from the keyboard. The LET statement added the two numbers. The PRINT statement sent the result to the display. The END statement sent control back to you, indicated by the "Ready" sent to the display.

When you are satisfied with a program you may keep it for another time by saying "SAVE". The workspace will still contain the program, but BASIC will have made a copy of it in your 'filespace'. Your filespace may contain an indefinite number of programs, while the workspace contains only one at a time. You may clear the workspace for another program by saying "NEW", or you may recall some other program from your filespace by saying "OLD". In either case, the command is followed by the name of the program you want to create or recall.

If you attempt to call up and old program, BASIC will check a directory (list of file names) for the program and load the program into the workspace. If it fails to find the program, you will be informed. (Most BASIC's do not provide a way to list the names of all the programs in your filespace, rather this is a service provided by your operating system. Consult your system's user's guide). The workspace may then be LISTed, modified by inserting or deleting lines, and/or RUN. "REPLACE" (REP for short) commands BASIC to file the modified contents of the workspace as the most recent version of the program in the filespace. A program in the file space may be UNSAVEd on some BASICs, while on other systems you must delete or purge the files with an operating system command.

Managing different versions of a program may be necessary during its development. You may create another program from an old one by renaming the workspace and saving the program under the new name, just as if you had typed the whole thing from scratch! The following example calls up a copy of ADDER, changes three lines of the program, names it MEAN, and saves the program under the new name.


OLD adder
Ready

10 REM  arithmetic mean of two numbers
20 INPUT A,B
30 LET C = (A+B)/2
35 PRINT "The mean is"
RENAME mean
Ready

SAVE
Ready

This feature can be very useful when testing a program or when making variations on a theme. ADDER is left unchanged by this process. The name of a program has no effect on it, but it should be meaningful so that you can remember it easily.

To leave BASIC, simply type "EXIT" or "BYE"; and you will find yourself back at the operating system level.

Summary: BASIC provides an interactive computing environment. The general pattern of this interaction is:

  1. Summon BASIC
  2. Say NEW or OLD
  3. Edit the workspace
  4. RUN the program for testing purposes
  5. If you are not satisfied, go back to step 3.
  6. SAVE the workspace
  7. Say BYE or go back to step 2.

In Chapter Six, we will see that the above could be characterized as a "Repeat Until Satisfied" process.

BASIC Statements

First let's state the things about BASIC statements that were implicitly suggested in the previous section:

INPUT accepts a number from the keyboard, converts it into a value and stores the value in the memory cell represented by the name of the variable in the INPUT statement. The INPUT statement displays a "?" and waits for a number and the RETURN key. We shall see that the INPUT statement can also accept alphabetic data.

PRINT converts the value of the variable named in the PRINT statement into a base ten number and displays it. The PRINT statement may also be used to display messages and alphabetic type data. (BASIC was invented before video terminals were commonplace. Perhaps DISPLAY or OUTPUT would be a better key word today, but such a change would have to be agreed upon by a standards committee).

LET evaluates an 'arithmetic expression' and assigns the resulting value to the variable on the left of the "=" sign. The LET statement is more restrictive than the algebraic equation you may have studied in mathematics. The LET statement is always a single variable, then an equal sign, then either a number, or a variable, or an expression involving several variables. Remember, there is always just one variable on the left of the equal sign. It is not a statement of equality, but a command to change the value of a variable to the value of the expression at the time the LET occurs in the context of the program. The full implication of this will become more apparent as we see how useful this can be.

END is always the last statement of the program. There can be only one END in a program and it will have the highest line number. The END statement transfers control from the current program to the BASIC command monitor. The program is, effectively, terminated and you are given a 'Ready' prompt for your next command.

REM annotates the program listing. It is used in a program to embed remarks which may be helpful to the programmer and others.

Variables are names used to represent the value stored in a cell of memory. The value of a variable may be changed by a program instruction. Its current value may be used in an expression at any time.

Operators must be explicitly written in the arithmetic expressions. The symbols used are shown in Figure 1-9.

Parentheses may be used to form 'sub-expressions' which are to be evaluated before performing other operations in the whole expression.

The above concepts work together to form programs. Consider as our first such example a program to convert Fahrenheit to Celsius:


NEW CELSIUS
Ready

10 INPUT F
20 LET C = 5*(F-32)/9
30 PRINT C
40 END
RUN
CELSIUS    3-SEP-1981  1:45

? 70
 21.1111

Ready

This program was written primarily to demonstrate the use of parentheses, as in the program to average two numbers. Let's run it for a different reason:


RUN
CELSIUS   23-NOV-1981   3:38

? 100,000,000
 37.7778

This time it appears that we tried to convert one-hundred million degrees Fahrenheit into Celsius but got only 37.7778 degrees rather than 37,777,778. The problem is that a comma is used to separate numbers in BASIC input. A number can never contain a comma. Unfortunately, most BASICs let a mistake like the above go unnoticed, so be careful.

Now let's consider the program on its own merit. If someone else RAN it without LISTing it, s/he would not know whether the program converts from F to C or C to F. This is remedied by displaying a 'prompt' before the input is solicited:


5 PRINT "Enter degrees Fahrenheit"
RUN
CELSIUS   3-SEP-1981   1:48

Enter degrees Fahrenheit
? 32
 0

Ready

(Your BASIC may use literal apostrophes rather than quote marks to enclose a string.) The program could produce a sentence of like "32 degrees Fahrenheit would be 0 degrees Celsius", but we shall defer such till Chapter 5.

This next example illustrates the reason the "=" in the LET statement is called the "assignment operator". Line 10 takes the constant value 1 and defines the value of variable I. Line 30 could be pronounced: "Form the value of I+1 and store the result back in I". The effect of this is to 'increment' "I" by one. The GOTO 20 statement sends control back to the statement on line 20.


NEW COUNTING
Ready

10 LET I = 1
20 PRINT I
30 LET I = I + 1
40 GOTO 20
50 END
RUN
COUNTING    3-SEP-1981   8:14

 1
 2
 3
 4
 ...   (forever!)

The program continually goes back to line 20. There is nothing to stop it. The END on line 50 will never be reached because of this 'closed loop'. You will have to interrupt the program from the keyboard by typing CTRL-C, or using the BREAK button, or some other button(s) germane to your system. (When a sample program in this book was interrupted, the message "PROGRAM INTERUPTUS!" appears at the end of the RUN). THIS IS NOT GOOD PROGRAMMING PRACTICE IN GENERAL AND IS DONE HERE TO KEEP SOME ILUSTRATIVE PROGRAMS SIMPLER. A PROGRAM WHICH IS TO BE USED BY OTHERS SHOULD NEVER END THIS WAY...

A GOTO is an 'unconditional branch'. To open the loop, a conditional statement can be used in place of the GOTO:


40 IF I < 100 THEN 20

If the condition "I < 100" is true, the branch will be performed. The COUNTING program will now count only to 100 when run. The less-than sign, "<", is called a relational operator. Other relational operators include ">" and "=". There is never any confusion between the assignment operator "=" and the relational operator "=" because they are used in different contexts.

The variable "I" in COUNTING served as a 'counter'. The same principle can be employed to 'accumulate' a sum of numbers:

NEW SUMMING
Ready

10 LET S = 0
20 INPUT X
30 LET S = S + X
40 PRINT S
50 GOTO 20
RUN
SUMMING    3-SEP-1981   5:08

? 17
 17
? 15
 32
? 19
 51
? -51
 0
...  (forever!)

The above program contains another closed loop. One way to terminate the loop would be to test the input value:


25 IF X = 0 THEN 60
60 PRINT S
DEL 40
RUN
SUMMING     3-SEP-1981   5:11

? 99
? 101
? 5
? 0
 205

Ready

Now, SUMMING quietly accepts numbers until a zero is input, then it displays the total. SUMMING is, effectively, an adding machine!

Now consider a rewrite of the COUNTING program using two new statements, FOR and NEXT, to control the loop:


NEW COUNTING
Ready

10 FOR I = 1 TO 5
20  PRINT I
30 NEXT I
40 END
RUN
COUNTING     3-SEP-1981   8:32

 1
 2
 3
 4
 5

Ready

"PRINT I" was sandwiched between the FOR and NEXT statements to repeat it five times. The variable used in the FOR/NEXT statements is available for reference within the loop. This sample program simply prints it out as the loop happens. This version of COUNTING is more aesthetically pleasing and more readable than our original. The PRINT statement was indented slightly to help show that it is between the FOR and NEXT. The indentation does not affect the meaning of the statement, it just helps us when reading the program in the future. Some versions of BASIC do not preserve indentation, in which case it is pointless to put it in.

Any number of statements may be sandwiched between the FOR and NEXT. The statements so sandwiched are said to be the 'body of the loop'. As an example, consider the following program that produces a conversion table for Celsius and Fahrenheit:


NEW FAHR
Ready

10 FOR C = 0 TO 100
20  LET F = 9*C/5 + 32
30  PRINT C,F
40 NEXT C
50 END

Run the above on your computer and see what it does!

Exercises:

  1. Compute the sum of the numbers from 1 to 100.
  2. Compute the product of the numbers from one to thirty.
  3. Write a program that will sum the numbers from M to N.
  4. Write a program that will form the product of the numbers from M to N.
  5. Write a program that will produce the sequence: 1, 2, 3, 5, 8, 13, 21,...
  6. where each number is the sum of the two previous numbers. Have the program INPUT two numbers to start the sequence.

Writing a Simple Program

{REWORD} At this point you may want to begin your detailed study of BASIC with the next section. On the other hand, you may want to follow this story of how a non-trivial program can be written using the few statements just introduced.

When the author was a young boy, a bank was built one block from his home. When the bank opened, he opened a savings account with the encouragement of his parents. When he went to the bank to make his second deposit, the teller took his passbook away for a seemingly long time and returned to accept his deposit. Upon looking at his new balance, he found that it was more than the total of his two deposits and that an entry had been made for something called "interest". The young boy appreciated the interest the bank paid him, especially since he forgot about the money for months at a time, but he did not understand anyone's explanations of why the bank did this.

A genuine explanation of why a bank does this is another story. However, the principle at work is quite appropriate: How did the teller compute the interest? Interest for one period (a year, quarter or month) is computed on the current balance of an account, and that interest is added to the account balance. Then the interest for the next period is computed. Since the balance has grown, the interest will be even more even though no new money has been deposited! The balance will grow at an increasing rate! This phenomenon is called "compound interest".

In the 1950's this evidently took a great deal of time for bank tellers to compute, so let's construct a program to compute the compound interest for a given balance, interest rate, and number of periods. To begin, we name the workspace:


NEW bank

The program needs to have the balance of the account, which we shall call "P", for "principal":


10 INPUT P

Note that "B" would work just as well, but the symbol "P" has been used traditionally for this purpose. Next, the program needs the interest rate:


20 INPUT I

Finally, we input the number of periods to be compounded:


30 INPUT N

Note that the interest rate is for one of the periods. If the interest is compounded monthly, then the interest rate should be the monthly interest rate. Also note that the order chosen to input the numbers is arbitrary and that to make the program useable by a stranger, the inputs should be prompted.

Next, we need to compute the amount of interest for one period from the current balance and the interest rate:


40 LET Q = P * I

Then we need to add the interest to the balance of the account:


50 LET P = P + Q

and subtract one from the number of periods passed:


60 LET N = N - 1

Then, if N is greater than zero, we repeat the above process to compound the interest:


70 IF N > 0 THEN 40

When the number of periods are exhausted (N is zero), the IF does not branch back to line 40, rather, the program continues on to line 80 where the balance is displayed:


80 PRINT P

After the PRINT comes the END of the program:


90 END

We have written a program that looks like it will do what we set out to do so we say RUN and give it some input:


RUN
BANK       3-SEP-1981   9:01

? 100
? 0.04
? 10

 148.024

The displayed number means that if $100 is deposited at 4% for ten periods, the balance will be $148.024. The bank will round off the four tenths of a cent, of course. This also shows why one must be careful in making computations with money since this rounding would (probably) be done each time the interest is compounded, rather than just at the end. Many BASIC programmers neglect this. In the "real world" much more attention is given to the accuracy of computation than is usually suggested in an introductory course. For now, please accept the fact that more sophisticated arithmetic is necessary in actual business applications where every penny must be preserved (accounted for). As you will see, appropriate measures can be taken to insure any practical level of accuracy.

Let's go back to our computation of the new balance. It was computed in two steps, first the amount of interest, then the new balance. The use of variable "Q" was only temporary, and can be dispensed with by substituting "P*I" directly for "Q" in line 50 and deleting line 40:


50 LET P = P + P*I
DEL 40

If you run the resulting program, you will find that it works just as well as the first.

Let's further observe that "P + P*I" can be factored, using the distributive law of algebra into: P*(1+I) with out changing its value:


50 LET P = P*(1 + I)

We RUN this and find that it works just the same. Then we realize that what we have been doing is to keep multiplying P by (1+I), N times. The ending balance is the value of P, times (1+I), times (1+I)... N times. Calling upon the exponentiation operator, "^", the whole program becomes


10 INPUT P
20 INPUT I
30 INPUT N
40 PRINT P*(1+I)^N
50 END
DEL 60-90

The proof of the pudding is in the eating, and sure enough, it works just as well!

If "55 PRINT P" were added to the original BANK program, the balance of the savings account would be displayed each time the interest is compounded. The final version of BANK cannot be amended to produce this output, because the amount is computed on one line, while the original BANK has a loop. That loop is now hidden inside the exponentiation operator!

Consider BANK to be our first complete program. The program in Figure 1-10 shows how other programs in this book will be presented. Each program is accompanied by a specification or description in English.

Summary: Often times, writing a program is a matter of recording a series of operations that you are familiar with but have never organized so carefully.

Exercises:

  1. Write BANK, using FOR/NEXT instead of IF-THEN loop.
  2. Experiment with values of I: 0, 0.04, 0.10, 1.0, 2.0.
  3. Write a program like SUMMING that accepts an initial deposit, and then goes into a loop asking for the number of months that have passed and a deposit amount. When a deposit of $0 is detected, the program should tell you the balance of the account.
  4. Write a program that prints out the population, P, of a colony with an annual growth rate, R, over N years.
  5. What would be the value of $24 invested at 6% annual interest for 352 years? (1626-1982).
  6. Write a program that calculates the balance of a savings account after n periods have passed, where a fixed amount is deposited each period. Test the program by having it print the balance each period and then hand check the computations.
  7. Given the population of a town or city, compute how many people will have heard a news story each hour after the story breaks using the assumption that each hour the number of new people hearing the news is a percentage of the number of people not yet having heard the news. The program should accept the population and the percentage as input.
  8. Radioactive decay is the process whereby a given percentage of radioactive material per unit of time pops like corn, leaving the remainder radio-active. Write a program that accepts a percentage and counts periods of time until 50% of the original amount is remaining. The length of time is called the half-life.
  9. Modify BANK so that it accepts an annual interest rate and whether the interest is to be compounded annually, monthly, or daily. (This would save the user from having to input 0.00833333, the monthly rate for 10% annual interest compounded monthly.)
  10. A hypothetical Xerox copier reduces the size of a copy by x%. What size will a dollar bill be after 10 copy-copies? How many copies must be made before it is half of its original size?
  11. Change Maker: Write a program which reads a number from the keyboard and considers it to be the price of an item, from 1 to 99 cents. The program should print, on separate lines, the name of each coin given in change for a dollar. For example, if the number 58 is read, the program prints
  12. 
    quarter
    dime
    nickel
    penny
    penny
    
    

    Modify the change-maker program to take into consideration that a clerk is given 1 roll of each coin to start with. When all of a coin is used up, change should be made using smaller coins, where possible. When the program runs out of pennies, it should terminate.

BASIC Syntax

We must have some way to show the legal forms of expressions and statements in BASIC. The method chosen for this book is simple. This section summarizes what we learned in the previous two sections as a demonstration of the method of showing forms.

Syntax diagrams consist of square and rounded boxes connected by lines. A rounded box indicates a character or group of characters used as a symbol in BASIC, such as parentheses or key words (PRINT, INPUT, etc). Each diagram has a starting point on the left. Arrows lead the way through the diagram to a single ending point on the right. Each and every path through the diagram is grammatically correct and has an unambiguous meaning. When a diagram is introduced, it is first described verbally, then restrictions are given along with the meaning of the form.

Figure 1-11 gives the characters called letters. Figure 1-12 gives all the digits. Note that the letter "O" is different from the digit zero "0". The two are dangerously close to each other on the standard keyboard. Beginners are t00 unsuspecting t0 see the difference after making the mistake, and then can n0t figure 0ut why their pr0gram d0esn't w0rk! Th0se experienced in reading mixed O0o's see them standing 0ut in the wr0ng c0ntext. The same hazard exists with the letter "l" and the digit "1". Letters and digits combine with other characters to form BASIC 'tokens', such as keywords, names of variables, and numbers.

In the remainder of this book, BASIC keywords (INPUT, LET, PRINT,...) are in upper case letters. Names of variables are in lower case. This was intended to help you see what part of a statement is part of the programming language and what is part of the problem. You may be limited to upper case on your system, but the programs in this book will work just as well.

Most all syntax diagrams also contain square boxes. A square box contains the name of another syntax diagram. The square box may be replaced by any of the possible forms given by the diagram it names. Figure 1-13 contains a square box referring to the syntax diagram for digits. The lines in the diagram show an arbitrary sequence of digits because each time we come around to the square box we may chose any digit from the digit syntax diagram. We have defined a new form and have named it 'digits'. The form name 'digits' is now available for use in later diagrams. This may seem like a lot of work to go through just to define a sequence of digits. Syntax diagrams can cover an entire language by building up forms from previously defined forms.

Figure 1-14 shows that a 'variable' is represented by a single letter.

Figure 1-15 shows that a 'number', as used in this chapter, has two possible forms. The simplest form is a sequence of digits. A number can also be a sequence of digits followed by a period (decimal point), followed by another sequence of digits. This means that 10560 and 1.92 are numbers and that .1 and 5. are not considered proper numbers. The latter two forms may be acceptable on your system but should be politely written as 0.1 and 5.

Figure 1-16 shows that a 'line number' looks just like a sequence of digits. Each 'line' in BASIC consists of a line number followed by one or more blanks followed by a 'statement' of some kind. Note that 'line' ends with a RETURN or ENTER keystroke.

Figure 1-17 shows the form of a statement. Note that the diagram shows the form of a statement, not the meaning. We could say that each statement begins with a key word, but not much more could be said about a general pattern. The diagram for 'expression' is developed in Chapter 2. We can see in the statement diagram three distinct uses of the equals sign (LET X = 5, FOR I = 1 TO 5, and IF X = 0 THEN...).

Figure 1-18 defines 'line number' as a sequence of digits. Line numbers appear only at the first of a line or after GOTO or THEN, in our simplified BASIC language.

The use of a blank space to separate tokens where necessary to improve readability is not shown in the diagrams.

Figure 1-19 shows that a 'program name' is any sequence of letters, limited in length (see the user's guide for your system). Most BASICs allow digits in the program name, see Exercise #5.

Figure 1-20 shows that a 'range' may consist of nothing, a single line number, a line number followed by a dash, or line number dash line number. A line number followed by just a dash refers to the range of lines starting with that line number through the END of the program. LIST without any range means to list the whole workspace, whereas DEL without any range does nothing, for safety's sake. Figure 1-21 shows the various commands that were introduced in Section 1.2. You should trace over the diagram, quizzing yourself on the meaning of each path through the diagram.

Figure 1-22 shows that a REM statement may be any sequence of characters whatsoever. Since programs are usually as terse as some poetry, remarks help us to follow the motivation of the programmer. Too many inappropriate remarks may distract from the story line. A blank REM statement may be used simply to make the program listing more readable. The REMark statement may be used to narrate the program logic in natural language. REMs can contain tables of information about variables in the BASIC program. This helps later when someone (yourself included) has to make sense of it so that it can be extended or modified.

All programs should have REMarks at the beginning giving the program's author and purpose, the date(s) it was written, references to any literature behind the concept of the program, etc:


REM   DATA-BASE MANAGEMENT PROGRAM
REM
REM   AUTHOR: Flash Coder
REM
REM   Copyright November 1988

Such a group of remarks are called the "program legend".

Your remarks should be short and to the point. For example:


REM  count how many empty boxes there are

can be simply:


REM  count empty boxes

without any loss of information while increasing clarity.

The REM is only for annotating the program listing. The information will not appear on the display when the program is RUN, only when it is LISTed. If you want to display a message, you must use a PRINT statement. What you say in a REMark has no effect on the program. A remark is essentially invisible to the interpreter/compiler.

Exercises:

  1. Design a pleasing pattern of remarks that will characterize
  2. programs you will write in the future.
  3. Write a set of syntax diagrams for the Old Testament.
  4. Draw a syntax diagram for a Library of Congress call number.
  5. Draw a set of syntax diagrams for a subset of a natural language of your choice (English, German, Latin).
  6. Most systems allow program names that contain digits as well as letters. Draw a syntax diagram for 'name' from a specification you will find in your BASIC user's guide.