Exponents

Try typing this program:

CLS

PRINT 4 ^ 3

To type the symbol ^, do this: while holding down the SHIFT key, tap this key:

+───┐

¦ ^ │

│ 6 │

└───┘

That symbol (^) is called a caret.

In that program, the "4 ^ 3" makes the computer use the number 4, three times. The computer will multiply together those three 4’s, like this: 4 times 4 times 4. Since "4 times 4 times 4" is 64, the computer will print:

64

In the expression "4 ^ 3", the 4 is called the base; the 3 is called the exponent.

Here’s another example:

CLS

PRINT 10 ^ 6

The "10 ^ 6" makes the computer use the number 10, six times. The computer will multiply together those six 10’s (like this: 10 times 10 times 10 times 10 times 10 times 10) and print the answer:

1000000

Here’s another example:

CLS

PRINT 3 ^ 2

The "3 ^ 2" makes the computer use the number 3, two times. The computer will multiply together those two 3’s (like this: 3 times 3) and print the answer:

9

Order of operations

The symbols +, -, *, /, and ^ are all called operations.

To solve a problem, the computer uses the three-step process taught in algebra and the "new math". For example, suppose you say:

PRINT 70 - 3 ^ 2 + 8 / 2 * 3

The computer will *not* begin by subtracting 3 from 70; instead, it will use the three-step process:

The problem is 70 - 3 ^ 2 + 8 / 2 * 3

Step 1: get rid of ^. Now the problem is 70 - 9 + 8 / 2 * 3

Step 2: get rid of * and /. Now the problem is 70 - 9 + 12

Step 3: get rid of + and -. The answer is 73

In each step, it looks from left to right. For example, in step 2, it sees / and gets rid of it before it sees *.

Though exponents are fun, the computer handles them slowly. For example, the computer handles 3 ^ 2 slower than 3 * 3. So for fast calculations, say 3 * 3 instead of 3 ^ 2.

Square roots

What positive number, when multiplied by itself, gives 9? The answer is 3, because 3 times itself is 9.

3 squared is 9. 3 is called the square root of 9.

To make the computer deduce the square root of 9, type this:

PRINT SQR(9)

The computer will print 3.

When you tell the computer to PRINT SQR(9), make sure you put the parentheses around the 9.

The symbol SQR is called a function. The number in parentheses (9) is called the function’s input (or argument or parameter). The answer, which is 3, is called the function’s output (or value).

SQR(9) gives the same answer as 9 ^ .5. The computer handles SQR(9) faster than 9 ^ .5.

Cube roots

What number, when multiplied by itself and then multiplied by itself *again*, gives 64? The answer is 4, because 4 times 4 times 4 is 64. The answer (4) is called the cube root of 64.

Here’s how to make the computer find the cube root of 64:

PRINT 64 ^ (1 / 3)

The computer will print 4.

EXP

The letter "e" stands for a special number, which is approximately 2.718281828459045. You can memorize that number easily, if you pair the digits:

2.7 18 28 18 28 45 90 45

That weird number is important in calculus, radioactivity, biological growth, and other areas of science. It’s calculated by this formula:

__1__ __ 1 __ __ 1 __ __ 1 __ __ 1 ____x__

e = 1 + + + + + + . . .

1 1*2 1*2*3 1*2*3*4 1*2*3*4*5

Therefore:

__1__ __1__ __ 1__ __ 1 ____x__

e = 1 + 1 + + + + + . . .

2 6 24 120

EXP(x) means e^{x}. For example, EXP(3) means e^{3}, which is e * e * e, which is:

2.718281828459045 * 2.718281828459045 * 2.718281828459045

EXP(4) means e^{4}, which is e * e * e * e. EXP(3.1) means e^{3.1}, which is more than e^{3} but less than e^{4}.

Here’s a practical application. Suppose you put $800 in a savings account, and the bank promises to give you 5% annual interest "compounded continuously". How much money will you have at the end of the year? The answer is 800 * EXP(.05).

Logarithms

Here are some powers of 2:

__x__ __2 ^{x}__

1 2

2 4

3 8

4 16

5 32

6 64

To compute the logarithm-base-2 of a number, find the number in the right-hand column; the answer is in the left column. For example, the logarithm-base-2 of 32 is 5. The logarithm-base-2 of 15 is slightly less than 4.

The logarithm-base-2 of 64 is 6. That fact is written:

log_{2} 64 is 6

It’s also written:

log 64

is 6

log 2

To make the computer find the logarithm-base-2 of 64, say:

PRINT LOG(64) / LOG(2)

The computer will print 6.

Here are some powers of 10:

__x__ __10 ^{x}__

1 10

2 100

3 1000

4 10000

5 100000

The logarithm-base-10 of 100000 is 5. The logarithm-base-10 of 1001 is slightly more than 3.

The logarithm-base-10 of 10000 is 4. That fact is written:

log_{10} 10000 is 4

It’s also written:

log 10000

is 4

log 10

To make the computer do that calculation, say:

PRINT LOG(10000) / LOG(10)

The computer will print 4.

The logarithm-base-10 is called the common logarithm. That’s the kind of logarithm used in high school and chemistry. So if a chemistry book says to find the logarithm of 10000, the book means the logarithm-base-10 of 10000, which is LOG(10000) / LOG(10).

What happens if you forget the base, and say just LOG(10000) instead of LOG(10000) / LOG(10)? If you say just LOG(10000), the computer will find the natural logarithm of 10000, which is log_{e} 10000 (where e is 2.718281828459045), which isn’t what your chemistry book wants.

Contrasts

The computer’s notation resembles that of arithmetic and algebra, but beware of these contrasts.…

Multiplication

To make the computer multiply, you must type an asterisk:

__Traditional notation__ __Computer notation__

2n 2 * n

5(n+m) 5 * (n + m)

nm n * m

Exponents

Put an exponent in parentheses, if it contains an operation:

__Traditional notation__ __Computer notation__

x^{n+2} x ^ (n + 2)

x^{3n} x ^ (3 * n)

5^{2/3} 5 ^ (2 / 3)

^{ 4}

2^{3} 2 ^ (3 ^ 4)

Fractions

Put a fraction’s numerator in parentheses, if it contains addition or subtraction:

__Traditional notation__ __Computer notation__

a+b

(a + b) / c

c

k-20

(k - 20) / 6

6

Put a denominator in parentheses, if it contains addition, subtraction, multiplication, or division:

__Traditional notation__ __Computer notation__

5 x

5 / (3 + x)

3+x

5a^{3}

5 * a ^ 3 / (4 * b)

4b

Mixed numbers

A mixed number is a number that contains a fraction. For example, 9½ is a mixed number. When you write a mixed number, put a plus sign before its fraction:

__Traditional notation__ __Computer notation__

9½ 9 + 1 / 2

If you’re using the mixed number in a further calculation, put the mixed number in parentheses:

__Traditional notation__ __Computer notation__

7 - 2¼ 7 - (2 + 1 / 4)

Clock

The computer has a built-in clock/calendar.

Setting the date & time

To set the date to January 24, 1996, you can run this

program —

CLS

DATE$ = "01-24-1996"

or give this DOS command (after leaving QBASIC):

C:\>date 01-24-1996

To set the time to 7 seconds after 1:45PM, you can run this program —

CLS

TIME$ = "13:45:07"

or give this DOS command:

C:\>time 13:45:07

Printing the date & time

After you’ve set the date & time, the computer’s clock/calendar will try to keep track of the date & time for you. Then whenever you want to find out the current date & time, run this program:

CLS

PRINT DATE$

PRINT TIME$

If you say —

PRINT TIMER

the computer will tell you how many seconds have elapsed since midnight.

This program makes the computer print the DATE$, TIME$, and TIMER across the top of your screen:

CLS

PRINT DATE$, TIME$, TIMER

The top of your screen will look like this:

07-29-1996 18:07:04 65223.85

The following program makes the computer look at the clock (and tell you the TIME$), then look at the clock *again* and tell you the new TIME$, then look at the clock *again* and tell you the new TIME$, etc.:

CLS

DO

PRINT TIME$

LOOP

For example, if the time starts at 18:07:04 (and eventually changes to 18:07:05 and then 18:07:06), the screen will look like this:

18:07:04

18:07:04

18:07:04

18:07:05

18:07:05

18:07:05

18:07:05

18:07:05

18:07:06

18:07:06

etc.

The program will continue telling you the time until you abort the program.

Clock battery

The typical computer contains a little battery, called a clock battery. While the computer is unplugged from the wall (or the computer’s main power switch is turned off), the clock battery continually sneaks enough electricity to the clock/calendar chips to keep them running, so they keep updating the date & time.

After several months or years, the battery will run out, and the chips will forget what the date & time are. Replace the battery, then reset the date & time.

Test your computer’s speed

How fast can your computer print the numbers from 1 to 1000? (The answer depends on the speed of your computer’s CPU chip, video card, and other components.) This program makes the computer print all the numbers from 1 to 1000, then brag about how fast it printed them:

CLS

starting.time = TIMER

FOR i = 1 TO 1000

PRINT i

NEXT

elapsed.time = TIMER - starting.time

PRINT "The elapsed time is"; elapsed.time; "seconds."

Line 2 makes the computer look at the clock’s TIMER and call that time the starting.time. The FOR..NEXT loop makes the computer print all the numbers from 1 to 1000. The line underneath (elapsed.time = TIMER - starting.time) makes the computer look at the clock’s TIMER again, notice how different it is from the starting.time, and call the difference the elapsed.time. The bottom line makes the computer print how much time elapsed.

For example, my 386SX-16 computer usually prints:

The elapsed time is 7.421875 seconds.

My 486DX2-66 computer is faster and usually prints:

The elapsed time is 1.976563 seconds.

How fast is *your* computer?

Try running the program several times. Sometimes you might get slightly different answers, since the TIMER isn’t very accurate.

For a different speed test, make the computer count up to 10000 instead of 1000. That makes the computer take about 10 times as long.

Try putting a semicolon at the end of the PRINT i line. That lets the computer print faster, since the computer no longer has to press the ENTER key after each number.

Try omitting the PRINT i line altogether, so the computer can just *think* about the numbers without bothering to print them. That lets the computer finish the program much faster. It tests how fast the CPU can *think*, rather than how fast the video circuitry can display printed answers.

Midnight problem

At midnight, TIMER is 0. At 1 second after midnight, TIMER is 1. At 2 seconds after midnight, TIMER is 2.

Since there are 60 seconds in a minute, 60 minutes in an hour, and 24 hours in a day, there are 86400 seconds in a day. At 1 second before midnight, TIMER is "86400 minus 1", which is 86399; but when midnight strikes, TIMER becomes 0 again.

To compute elapsed.time, you normally take the current time (TIMER) and subtract the starting.time:

elapsed.time = TIMER - starting.time

That formula works if TIMER is a bigger number than starting.time.

But suppose a program starts running just before midnight and ends just after midnight. Since the starting.time is nearly 86400 and the TIMER (current time) is just slightly bigger than 0, the formula "TIMER - starting.time" gives a negative number, which is *not* the correct calculation for elapsed.time, since elapsed.time cannot be negative!

Here’s how to correct the definition of elapsed.time. Instead of giving this one-line definition —

elapsed.time = TIMER - starting.time

give this two-line definition:

elapsed.time = TIMER - starting.time

IF elapsed.time < 0 THEN elapsed.time = elapsed.time + 86400

So the program to test your program’s speed should be:

CLS

starting.time = TIMER

FOR i = 1 TO 1000

PRINT i

NEXT

elapsed.time = TIMER - starting.time

IF elapsed.time < 0 THEN elapsed.time = elapsed.time + 86400

PRINT "The elapsed time is"; elapsed.time; "seconds"

If you omit the shaded line, the program will work usually, but not at midnight. The typical novice programmer forgets to insert that line, thinks the program works fine without it, and gets surprised years later by a midnight phone call from an upset user wondering why the computer reports that the elapsed time is a negative number.

LOOP UNTIL

This program prints the letter "x" repeatedly, for .3 seconds:

CLS

starting.time = TIMER

DO

PRINT "x";

elapsed.time = TIMER - starting.time

IF elapsed.time < 0 THEN elapsed.time = elapsed.time + 86400

LOOP UNTIL elapsed.time >= .3

Line 2 makes the computer look at the clock’s TIMER and call that time the starting.time. The PRINT line makes the computer print an "x". The other indented lines compute the elapsed.time. The bottom line says: do the loop again and again, until the elapsed time is at least .3.

So that program makes the computer print x’s for about .3 seconds.

Experiment! Run that program, and see how many x’s *your* computer can print in .3 seconds.

If you run that program several times, you’ll get slightly different answers, since the TIMER isn’t very accurate.

In the bottom line, try changing the .3 to a different number, to see how many x’s your computer can print in a different amount of time. Even if you replace the .3 by a tiny number, the computer will print at least one x, since the computer does the PRINT line before encountering the definition of elapsed.time and the LOOP condition.

Pause loop

This program makes the computer print "I’m going to take a nap", then pause for 5 seconds, then print "Now I woke up":

CLS

PRINT "I'm going to take a nap"

SLEEP 5

PRINT "Now I woke up"

This fancier program accomplishes the same goal:

CLS

PRINT "I'm going to take a nap"

starting.time = TIMER

DO

elapsed.time = TIMER - starting.time

IF elapsed.time < 0 THEN elapsed.time = elapsed.time + 86400

LOOP UNTIL elapsed.time >= 5

PRINT "Now I woke up"

Line 2 makes the computer print "I’m going to take a nap". The next line (starting.time = TIMER) makes the computer look at the clock’s TIMER and call that time the starting.time. The DO loop makes the computer look at the time repeatedly, until the elapsed.time is at least 5 seconds. After those 5 seconds of at of staring at the clock, the computer finally does the bottom line, which makes the computer print "Now I woke up". Since the loop’s only purpose is to make the computer pause for 5 seconds, the loop is called a pause loop.

The fancy program (which says LOOP UNTIL) has two advantages over the simple program (which says SLEEP):

In the SLEEP program, if the human presses a key while the computer is SLEEPing, the computer wakes up immediately. In the LOOP UNTIL program, the computer ignores the human until 5 seconds have passed, so the LOOP UNTIL program ensures that the computer really DOES pause for 5 seconds. The only way the human can interrupt the computer’s pause loop is to abort the program (by pressing Ctrl with PAUSE/BREAK).

In the LOOP UNTIL program, you can make the computer loop for 5.1 seconds instead of 5 seconds, by changing the 5 to 5.1. You can’t create a SLEEP program that sleeps for 5.1 seconds, since the SLEEP command prohibits decimals: if you try to say SLEEP 5.1, the computer will do SLEEP 5 instead.

__FOR...NEXT__ Here’s another way to make the computer take a nap:

CLS

PRINT "I'm going to take a nap"

FOR i = 1 TO 50000: NEXT

PRINT "Now I woke up"

The FOR line makes the computer count up to 50000. Since the computer doesn’t print anything while counting, the FOR line acts as a pause.

How long will the pause last? If your computer is very fast (a Pentium), the pause will last just a few seconds; if your computer is very slow (an 8088), counting to 50000 will take longer, and the pause will last *many* seconds.

How long will *your* computer pause? Experiment!

If you want the computer to pause for 3 seconds, raise or lower the number 50000 until the pause takes 3 seconds. If you someday buy a faster computer, to keep the 3-second pause you must raise the number in the FOR line.

Stripping

Sometimes the computer prints *too* much info: you wish the computer would print less, to save yourself the agony of reading excess info irrelevant to your needs. Whenever the computer prints too much info about a numerical answer, use ABS, FIX, INT, CINT, or SGN.

ABS removes any minus sign. For example, the ABS of -3.89 is 3.89. So if you say PRINT ABS(-3.89), the computer will print just 3.89.

FIX removes any digits after the decimal point. For example, the FIX of 3.89 is 3. So if you say PRINT FIX(3.89), the computer will print just 3. The FIX of -3.89 is -3.

CINT rounds to the NEAREST integer. For example, the CINT of 3.89 is 4; the CINT of -3.89 is -4.

INT rounds the number DOWN to an integer that’s LOWER. For example, the INT of 3.89 is 3 (because 3 is an integer that’s lower than 3.89); the INT of -3.89 is -4 (because -4 is lower than -3.89).

SGN removes ALL the digits and replaces them by a 1 — unless the number is 0. For example, the SGN of 3.89 is 1. The SGN of -3.89 is -1. The SGN of 0 is just 0.

ABS, FIX, CINT, INT, and SGN are all called stripping functions or strippers or diet functions or diet pills, because they strip away the number’s excess fat and reveal just the fundamentals that interest you.

Here are more details about those five functions.…

ABS

To find the absolute value of a negative number, just omit the number’s minus sign. For example, the absolute value of -7 is 7.

The absolute value of a positive number is the number itself. For example, the absolute value of 7 is 7. The absolute value of 0 is 0.

To make the computer find the absolute value of -7, type this:

PRINT ABS(-7)

The computer will print:

7

Like SQR, ABS is a function: you must put parentheses after the ABS.

__Distance__ Since ABS omits the minus sign, ABS turns negative numbers into positive numbers. Use ABS whenever you insist that an answer be positive.

For example, ABS helps solve math & physics problems about "distance", since the "distance" between two points is always a positive number and cannot be negative.

This program computes the distance between two numbers:

CLS

PRINT "I will find the distance between two numbers."

INPUT "What's the first number"; x

INPUT "What's the second number"; y

PRINT "The distance between those numbers is"; ABS(x - y)

When you run that program, suppose you say that the first number is 4 and the second number is 7. Since x is 4, and y is 7, the distance between those two numbers is ABS(4 - 7), which is ABS(-3), which is 3.

If you reverse those two numbers, so that x is 7 and y is 4, the distance between them is ABS(7 - 4), which is ABS(3), which is still 3.

FIX

An integer is a number that has no decimal point. For example, these are integers: 17, 238, 0, and -956.

If a number contains a decimal point, you can turn the number into an integer in several ways.

The simplest is to delete all the digits after the decimal point. That’s called the FIX of the number.

For example, the FIX of 3.89 is 3. So if you say PRINT FIX (3.89), the computer will print just 3.

The FIX of -3.89 is -3. The FIX of 7 is 7. The FIX of 0 is 0.

CINT

A more sophisticated way to turn a number into an integer is to *round* the number to the *nearest* integer. That’s called CINT (which means "Convert to INTeger"). For example, the CINT of 3.9 is 4 (because 3.9 is closer to 4 than to 3).

Like FIX, CINT deletes all the digits after the decimal point; but if the digit just after the decimal point is 5, 6, 7, 8, or 9, CINT "rounds up" by adding 1 to the digit before the decimal point.

Here are more examples:

CINT(3.9) is 4 CINT(-3.9) is -4

CINT(3.1) is 3 CINT(-3.1) is -3

CINT(3.5) is 4 CINT(-3.5) is -4

__Highest number__ The highest number CINT can produce is 32767. If you try to go higher than 32767 or lower than -32768, the computer will gripe by saying "Overflow".

__Exploratory program__ To explore the mysteries of rounding, run this program:

CLS

INPUT "What's your favorite number"; x

PRINT CINT(x)

In that program, the INPUT line asks you to type a number x. The bottom line prints your number, but rounded to the nearest integer. For example, if you type 3.9, the bottom line prints 4.

INT

Like FIX and CINT, INT turns a number into an integer. Though INT is slightly harder to understand than FIX and CINT, INT is more useful!

INT rounds a number *down* to an integer that’s *lower*. For example, the INT of 3.9 is 3 (because 3 is an integer that’s lower than 3.9). The INT of -3.9 is -4 (because a temperature of -4 is lower and colder than a temperature of -3.9). The INT of 7 is simply 7.

__Exploratory program__ To explore further the mysteries of rounding, run this program:

CLS

INPUT "What's your favorite number"; x

PRINT "Your number rounded down is"; INT(x)

PRINT "Your number rounded up is"; -INT(-x)

PRINT "Your number rounded to the nearest integer is"; INT(x + .5)

In that program, the INPUT line asks you to type a number x.

The next line prints your number rounded *down*. For example, if you input 3.9, the computer prints 3.

The next line, PRINT -INT(-x), prints your number rounded *up*. For example if you input 3.9, the computer prints 4.

The bottom line prints your number rounded to the *nearest* integer. For example, if you input 3.9, the computer will print 4.

Here’s the rule: if x is a number, INT(x) rounds x down; -INT(-x) rounds x up; INT(x + .5) rounds x to the nearest integer.

__Why INT is better than CINT and FIX__ To round x to the nearest integer, you can say either CINT(x) or INT(x + .5). Alas, CINT(x) handles just numbers from -32768 to 32767. But INT(x + .5) can handle *any* number!

Another advantage of INT is that it works in *all* versions of BASIC. Even the oldest, most primitive versions of BASIC understand INT. Alas, CINT and FIX work in just a *few* versions of BASIC, such as QBASIC. To make sure your programs work on *many* computers, use INT rather than CINT or FIX.

In the rest of this book, I’ll emphasize INT.

__Supermarket math__ Rounding down and rounding up are useful in the supermarket.…

Suppose some items are marked "30¢ each", and you have just two dollars. How many can you buy? Two dollars divided by 30¢ is 6.66667; rounding *down* to an integer, you can buy 6.

Suppose some items are marked "3 for a dollar", and you want to buy just one of them. How much will the supermarket charge you? One dollar divided by 3 is 33.3333¢; rounding *up* to an integer, you will be charged 34¢.

__Fancier rounding__ By using INT, you can do fancier kinds of rounding:

to round x to the nearest thousand, ask for INT(x / 1000 + .5) * 1000

to round x to the nearest thousandth, ask for INT(x / .001 + .5) * .001

This program rounds a number, so that it will have just a *few* digits after the decimal point:

CLS

INPUT "What's your favorite number"; x

INPUT "How many digits would you like after its decimal point"; d

b = 10 ^ -d

PRINT "Your number rounded is"; INT(x / b + .5) * b

Here’s a sample run:

What's your favorite number? __4.28631__

How many digits would you like after its decimal point? __2__

Your number rounded is 4.29

SGN

If a number is negative, its sign is -1. For example, the sign of -546 is -1.

If a number is positive, its sign is +1. For example the sign of 8231 is +1.

The sign of 0 is 0.

The computer’s abbreviation for "sign" is "SGN". So if you say —

PRINT SGN(-546)

the computer will print the sign of -546; it will print -1.

If you say —

PRINT SGN(8231)

the computer will print the sign of 8231; it will print 1.

If you say —

PRINT SGN(0)

the computer will print the sign of 0; it will print 0.

SGN is the opposite of ABS. Let’s see what both functions do to -7.2. ABS removes the minus sign, but leaves the digits:

ABS(-7.2) is 7.2

SGN removes the digits, but leaves the minus sign:

SGN(-7.2) is -1

The Latin word for *sign* is signum. Most mathematicians prefer to talk in Latin — they say "signum" instead of "sign" — because the English word "sign" sounds too much like the trigonometry word "sine". So mathematicians call SGN the signum function.

Random numbers

Usually, the computer is predictable: it does exactly what you say. But sometimes, you want the computer to be *un*predictable.

For example, if you’re going to play a game of cards with the computer and tell the computer to deal, you want the cards dealt to be unpredictable. If the cards were predictable — if you could figure out exactly which cards you and the computer would be dealt — the game would be boring.

In many other games too, you want the computer to be unpredictable, to "surprise" you. Without an element of surprise, the game would be boring.

Being unpredictable increases the pleasure you derive from games — and from art. To make the computer act artistic, and create a new *original* masterpiece that’s a "work of art", you need a way to make the computer get a "flash of inspiration". Flashes of inspiration aren’t predictable: they’re surprises.

Here’s how to make the computer act unpredictably.…

RND is a RaNDom decimal, bigger than 0 and less than 1. For example, it might be .6273649 or .9241587 or .2632801. Every time your program mentions RND, the computer concocts another decimal:

CLS

PRINT RND

PRINT RND

PRINT RND

The computer prints:

.7055475

.533424

.5795186

The first time your program mentions RND, the computer chooses its favorite decimal, which is .7055475. Each succeeding time your program mentions RND, the computer sues the previous decimal to concoct a new one. It uses .7055475 to concoct .533424, which it uses to concoct .5795186. The process by which the computer concocts each new decimal from the previous one is weird enough so we humans cannot detect any pattern.

This program prints lots of decimals — and pauses a second after each decimal, so you have a chance to read it:

CLS

DO

PRINT RND

SLEEP 1

LOOP

About half the decimals will be less than .5, and about half will be more than .5.

Most of the decimals will be less than .9. In fact, about 90% will be.

About 36% of the decimals will be less than .36; 59% will be less than .59; 99% will be less than .99; 2% will be less than .02; a quarter of them will be less than .25; etc. You might see some decimal twice, though most of the decimals will be different from each other. When you get tired of running that program and seeing decimals, abort the program (by pressing Ctrl with PAUSE/BREAK).

If you run that program again, you’ll get exactly the same list of decimals again, in the same order.

RANDOMIZE TIMER

If you’d rather see a different list of decimals, say RANDOMIZE TIMER at the beginning of the program:

CLS

RANDOMIZE TIMER

DO

PRINT RND

SLEEP 1

LOOP

When the computer sees RANDOMIZE TIMER, the computer looks at the clock and manipulates the time’s digits to produce the first value of RND.

So the first value of RND will be a number that depends on the time of day, instead of the usual .7055475. Since the first value of RND will be different than usual, so will the second, and so will the rest of the list.

Every time you run the program, the clock will be different, so the first value of RND will be different, so the whole list will be different — unless you run the program at exactly the same time the next day, when the clock is the same. But since the clock is accurate to a tiny fraction of a second, the chance of hitting the same time is extremely unlikely.

Love or hate?

Who loves ya, baby? This program tries to answer that question:

CLS

RANDOMIZE TIMER

DO

INPUT "Type the name of someone you love..."; name$

IF RND < .67 THEN

PRINT name$; " loves you, too"

ELSE

PRINT name$; " hates your guts"

END IF

LOOP

The RANDOMIZE TIMER line makes the value of RND depend on the clock. The INPUT line makes the computer wait for the human to type a name. Suppose he types Suzy. Then name$ is "Suzy". The IF line says there’s a 67% chance that the computer will print "Suzy loves you, too!", but there’s a 33% chance the computer will instead print "Suzy hates your guts". The words DO and LOOP make the computer do the routine again and again, until the human aborts the program. The run might look like this:

Type the name of someone you love...? __Suzy__

Suzy loves you, too

Type the name of someone you love...? __Joan__

Joan hates your guts

Type the name of someone you love...? __Alice__

Alice loves you, too

Type the name of someone you love...? __Fred__

Fred loves you, too

Type the name of someone you love...? __Uncle Charlie__

Uncle Charlie hates your guts

Coin flipping

This program makes the computer flip a coin:

CLS

RANDOMIZE TIMER

IF RND < .5 THEN PRINT "heads" ELSE PRINT "tails"

The IF line says there’s a 50% chance that the computer will print "heads"; if the computer does *not* print "heads", it will print "tails".

Until you run the program, you won’t know which way the coin will flip; the choice is random. Each time you run the program, the computer will flip the coin again; each time, the outcome is unpredictable.

__Bets__ Let’s permit the human to bet on whether the computer will say "heads" or "tails". Here’s how:

CLS

RANDOMIZE TIMER

10 INPUT "Do you want to bet on heads or tails"; bet$

IF bet$ <> "heads" AND bet$ <> "tails" THEN

PRINT "Please say heads or tails"

GOTO 10

END IF

IF RND < .5 THEN coin$ = "heads" ELSE coin$ = "tails"

PRINT "The coin says "; coin$

IF coin$ = bet$ THEN PRINT "You win" ELSE PRINT "You lose"

The line numbered 10 makes the computer ask:

Do you want to bet on heads or tails?

The next line makes sure the human says "heads" or "tails": if the human’s answer isn’t "heads" and isn’t "tails", the computer gripes. The bottom three lines make the computer flip a coin and determine whether the human won or lost the bet.

Here’s a sample run:

Do you want to bet on heads or tails? __heads__

The coin says tails

You lose

Here’s another:

Do you want to bet on heads or tails? __tails__

The coin says tails

You win

Here’s another:

Do you want to bet on heads or tails? __tails__

The coin says heads

You lose

__Money__ To make the program more fun, let the human use money when betting:

CLS

RANDOMIZE TIMER

bankroll = 100

4 PRINT "You have"; bankroll; "dollars"

5 INPUT "How many dollars do you want to bet"; stake

IF stake > bankroll THEN PRINT "You don't have that much! Bet less!": GOTO 5

IF stake < 0 THEN PRINT "You can't bet less than nothing!": GOTO 5

IF stake = 0 THEN PRINT "I guess you don't want to bet anymore": GOTO 20

10 INPUT "Do you want to bet on heads or tails"; bet$

IF bet$ <> "heads" AND bet$ <> "tails" THEN

PRINT "Please say heads or tails"

GOTO 10

END IF

IF RND < .5 THEN coin$ = "heads" ELSE coin$ = "tails"

PRINT "The coin says "; coin$

IF coin$ = bet$ THEN

PRINT "You win"; stake; "dollars"

bankroll = bankroll + stake

GOTO 4

END IF

PRINT "You lose"; stake; "dollars"

bankroll = bankroll - stake

IF bankroll > 0 THEN GOTO 4

PRINT "You're broke! Too bad!"

20 PRINT "Thanks for playing with me! You were fun to play with!"

PRINT "I hope you play again sometime!"

Line 3 (bankroll = 100) gives the human a $100 *bankroll*, so the human starts with $100. The next line makes the computer say:

You have 100 dollars

The line numbered 5 makes the computer ask:

How many dollars do you want to bet?

The number that the human inputs (the number of dollars that the human bets) is called the human’s *stake*. The next three lines (which say "IF stake") make sure the stake is reasonable.

The line numbered 10 gets the human to bet on heads or tails. The next few lines flip the coin, determine whether the human won or lost the bet, and then send the computer back to line 4 for another round (if the human isn’t broke yet). The bottom three lines say good-bye to the human.

Here’s a sample run:

You have 100 dollars

How many dollars do you want to bet? __120__

You don't have that much! Bet less!

How many dollars do you want to bet? __75__

Do you want to bet on heads or tails? __heads__

The coin says tails

You lose 75 dollars

You have 25 dollars

How many dollars do you want to bet? __10__

Do you want to bet on heads or tails? __tails__

The coin says tails

You win 10 dollars

You have 35 dollars

How many dollars do you want to bet? __35__

Do you want to bet on heads or tails? __tails__

The coin says heads

You lose 35 dollars

You're broke! Too bad!

Thanks for playing with me! You were fun to play with!

I hope you play again sometime!

__Display all the dollars__ To make the output prettier, replace line 4 by this group of lines:

4 PRINT

PRINT "You have"; bankroll; "dollars! Here they are:"

FOR i = 1 TO bankroll

PRINT "$";

NEXT

Now the run looks like this:

You have 100 dollars! Here they are:

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

$$$$$$$$$$$$$$$$$$$$

How many dollars do you want to bet? __120__

You don't have that much! Bet less!

How many dollars do you want to bet? __75__

Do you want to bet on heads or tails? __heads__

The coin says tails

You lose 75 dollars

You have 25 dollars! Here they are:

$$$$$$$$$$$$$$$$$$$$$$$$$

How many dollars do you want to bet? __10__

Do you want to bet on heads or tails? __tails__

The coin says tails

You win 10 dollars

You have 35 dollars! Here they are:

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

How many dollars do you want to bet? __35__

Do you want to bet on heads or tails? __tails__

The coin says heads

You lose 35 dollars

You're broke! Too bad!

Thanks for playing with me! You were fun to play with!

I hope you play again sometime!

Random integers

If you want a random integer from 1 to 100, ask for 1 + INT(RND * 100). Here’s why:

RND is a decimal, bigger than 0 and less than 1.

So RND * 10 is a decimal, bigger than 0 and less than 10.

So INT(RND * 10) is an integer, at least 0 and no more than 9.

So 1 + INT(RND * 10) is an integer, at least 1 and no more than 10.

This program plays a guessing game:

CLS

RANDOMIZE TIMER

PRINT "I'm thinking of a number from 1 to 10."

computer.number = 1 + INT(RND * 10)

10 INPUT "What do you think my number is"; guess

IF guess < computer.number THEN PRINT "Your guess is too low.": GOTO 10

IF guess > computer.number THEN PRINT "Your guess is too high.": GOTO 10

PRINT "Congratulations! You found my number!"

Line 3 makes the computer say:

I'm thinking of a number from 1 to 10.

The next line makes the computer think of a random number from 1 to 10; the computer’s number is called "computer.number". The INPUT line asks the human to guess the number.

If the guess is less than the computer’s number, the first IF line makes the computer say "Your guess is too low" and then GOTO 10, which lets the human guess again. If the guess is *greater* than the computer’s number, the bottom IF line makes the computer say "Your guess is too high" and then GOTO 10.

When the human guesses correctly, the computer arrives at the bottom line, which prints:

Congratulations! You found my number!

Here’s a sample run:

I'm thinking of a number from 1 TO 10.

What do you think my number is? __3__

Your guess is too low.

What do you think my number is? __8__

Your guess is too high.

What do you think my number is? __5__

Your guess is too low.

What do you think my number is? __6__

Congratulations! You found my number!

Dice

This program makes the computer roll a pair of dice:

CLS

RANDOMIZE TIMER

PRINT "I'm rolling a pair of dice"

a = 1 + INT(RND * 6)

PRINT "One of the dice says"; a

b = 1 + INT(RND * 6)

PRINT "The other says"; b

PRINT "The total is"; a + b

Line 3 makes the computer say:

I'm rolling a pair of dice

Each of the dice has 6 sides. The next line, a = 1 + INT(RND * 6), rolls one of the dice, by picking a number from 1 to 6. The line saying "b = 1 + INT(RND * 6)" rolls the other. The bottom line prints the total.

Here’s a sample run:

I'm rolling a pair of dice

One of the dice says 3

The other says 5

The total is 8

Here’s another run:

I'm rolling a pair of dice

One of the dice says 6

The other says 4

The total is 10

Daily horoscope

This program predicts what will happen to you today:

CLS

RANDOMIZE TIMER

PRINT "You will have a ";

SELECT CASE 1 + INT(RND * 5)

CASE 1

PRINT "wonderful";

CASE 2

PRINT "fairly good";

CASE 3

PRINT "so-so";

CASE 4

PRINT "fairly bad";

CASE 5

PRINT "terrible";

END SELECT

PRINT " day today!"

The computer will say —

You will have a wonderful day today!

or —

You will have a terrible day today!

or some in-between comment. That’s because the SELECT CASE line makes the computer pick a random integer from 1 to 5.

For inspiration, run that program when you get up in the morning. Then notice whether your day turns out the way the computer predicts!

Character codes

You can use these code numbers:

Alt key

Here’s how to type the symbol ñ, whose code number is 164. Hold down the Alt key; and while you keep holding down the Alt key, type 164 *by using the numeric keypad* (the number keys on the far right side of the keyboard). When you finish typing 164, lift your finger from the Alt key, and you’ll see ñ on your screen!

The Alt key works reliably for most numbers in that chart but *not* for numbers 1-27 and 127.

You can use the Alt key in your program. For example, try typing this program:

CLS

PRINT "In Spanish, tomorrow is mañana"

While typing that program, make the symbol ¤ by typing 164 on the numeric keypad while holding down the Alt key. When you run that program, the computer will print:

In Spanish, tomorrow is mañana

CHR$

Here’s another way to type the symbol ñ:

CLS

PRINT CHR$(164)

When you run that program, the computer will print the CHaRacter whose code number is 164. The computer will print:

ñ

This program makes the computer print "In Spanish, tomorrow is mañana":

CLS

PRINT "In Spanish, tomorrow is ma"; CHR$(164); "ana"

That PRINT line makes the computer print "In Spanish, tomorrow is ma", then print character 164 (which is ñ), then print "ana".

__Quotation marks__ Since character 34 is a quotation mark, this program prints a quotation mark:

CLS

PRINT CHR$(34)

Suppose you want the computer to print:

Scholars think "Hamlet" is a great play.

To make the computer print the quotation marks around "Hamlet", use CHR$(34), like this:

CLS

PRINT "Scholars think "; CHR$(34); "Hamlet"; CHR$(34); " is a great play."

__The entire chart__ CHR$ works reliably for all numbers in that chart. This program prints, on your screen, all the symbols in the chart:

CLS

FOR i = 1 TO 6: PRINT CHR$(i);: NEXT

PRINT CHR$(8);

FOR i = 14 TO 27: PRINT CHR$(i);: NEXT

FOR i = 33 TO 254: PRINT CHR$(i);: NEXT

__Missing codes__ That chart shows *most* code numbers from 1 to 254 but skips the following mysterious code numbers: 7, 9-13, and 28-32. Here’s what those mysterious code numbers do.…

In a PRINT statement, CHR$(7) makes the computer beep. Saying —

PRINT CHR$(7);

has the same effect as saying:

BEEP

If you say —

PRINT "hot"; CHR$(7); "dog"

the computer will print "hot", then beep, then turn the "hot" into "hotdog".

CHR$(9) makes the computer press the TAB key, so your writing is indented. For example, if you say —

PRINT "hot"; CHR$(9); "dog"

the computer will print "hot", then indent by pressing the TAB key, then print "dog", so you see this:

hot

dog

CHR$(31) makes the computer move the cursor (the blinking underline) down to the line below. For example, if you say —

PRINT "hot"; CHR$(31); "dog"

the computer will print "hot", then move down, then print "dog" on the line below, so you see this:

hot

dog

You can move the cursor in all four directions:

CHR$(28) moves the cursor toward the right

CHR$(29) moves the cursor toward the left

CHR$(30) moves the cursor up

CHR$(31) moves the cursor down

CHR$(11) moves the cursor all the way to the screen’s top left corner, which is called the home position.

CHR$(32) is a blank space. It’s the same as " ".

CHR$(12) erases the entire screen. Saying —

PRINT CHR$(12);

has the same effect as saying:

CLS

CHR$(10) and CHR$(13) each make the computer press the ENTER key.

Printing on paper

When printing onto paper, make your program’s bottom line say:

LPRINT CHR$(12);

That makes the printer eject the paper.

Codes 33-126 print on paper okay. As on the screen, code 32 prints a blank space. Other codes print okay on some printers but wrong on other printers. Experiment, and see which codes *your* printer can print correctly.

If you want to print codes 128-254 on a typical laser printer (such as a Hewlett-Packard Laserjet 2), put this line at the top of your program (just under the CLS):

LPRINT CHR$(27); "(10U";

Type that line carefully. In the quotation marks, make sure you type just a single parenthesis, then the number 10, then a capital U.

A typical dot-matrix printer (such as an Epson LQ-570) normally prints 10 characters per inch. To make the characters thinner, so you get 17 characters per inch, say:

LPRINT CHR$(15);

To cancel that 17-characters-per-inch command, say:

LPRINT CHR$(18);

To make the characters wider, so you get 5 characters per inch, say:

LPRINT CHR$(14);

To cancel that command, say:

LPRINT CHR$(20);

ASC

The code numbers from 32 to 126 are for characters that you can type on the keyboard easily. Established by a national committee, those code numbers are called the American Standard Code for Information Interchange, which is abbreviated ASCII, which is pronounced "ass key".

Programmers say, "the ASCII code number for A is 65". If you say —

PRINT ASC("A")

the computer will print the ASCII code number for "A". It will print:

65

If you say PRINT ASC("B"), the computer will print 66. If you say PRINT ASC("b"), the computer will print 97.

If you say PRINT ASC("ñ"), the computer will print 164 (which is the code number for ñ), even though ñ isn’t an ASCII character.

String analysis

Let’s analyze the word "smart".

Length

Since "smart" has 5 characters in it, the length of "smart" is 5. If you say —

PRINT LEN("smart")

the computer will print the LENgth of "smart"; it will print:

5

Left, right, middle

The left two characters of "smart" are "sm". If you say —

PRINT LEFT$("smart", 2)

the computer will print:

sm

Try this program:

CLS

a$ = "smart"

PRINT LEFT$(a$, 2)

Line 2 says a$ is "smart". The bottom line says to print the left 2 characters of a$, which are "sm". The computer will print:

sm

If a$ is "smart", here are the consequences.…

LEN(a$) is the LENgth of a$. It is 5.

LEFT$(a$, 2) is the LEFT 2 characters of a$. It is "sm".

RIGHT$(a$, 2) is the RIGHT 2 characters of a$. It is "rt".

MID$(a$, 2) begins in the MIDdle of a$, at the 2^{nd} character. It’s "mart".

MID$(a$, 2, 3) begins at 2^{nd} character and includes 3 characters. It’s "mar".

__Changing the middle__ You can change the middle of a string, like this:

CLS

a$ = "bunkers"

MID$(a$, 2) = "owl"

PRINT a$

Line 2 says a$ is "bunkers". The MID$ line changes the middle of a$ to "owl"; the change begins at the 2^{nd} character of a$. The bottom line prints:

bowlers

Here’s a variation:

CLS

a$ = "bunkers"

MID$(a$, 2) = "ad agency"

PRINT a$

Line 2 says a$ is "bunkers". The MID$ line says to change the middle of a$, beginning at the 2^{nd} character of a$. But "ad agency" is too long to become part of "bunkers". The computer uses as much of "ad agency" as will fit in "bunkers". The computer will print:

bad age

Another variation:

CLS

a$ = "bunkers"

MID$(a$, 2, 1) = "owl"

PRINT a$

Line 2 says a$ is "bunkers". The MID$ line says to change the middle of a$, beginning at the 2^{nd} character of a$. But the ",1" makes the computer use just 1 letter from "owl". The bottom line prints:

bonkers

Capitals

Capital letters (such as X, Y, and Z) are called upper-case letters. Small letters (such as x, y, and z) are called lower-case letters.

If you say —

PRINT UCASE$("We love America")

the computer will print an upper-case (capitalized) version of "We love America"), like this:

WE LOVE AMERICA

If you say —

PRINT LCASE$("We love America")

the computer will print a lower-case version of "We love America", like this:

we love america

__Accents__ Unfortunately, the computer doesn’t know how to capitalize an accented letter (such as ñ).

For example, suppose you say:

PRINT UCASE$("mañana")

Since the computer doesn’t know how to capitalize the ¤, the computer prints:

MAñANA

If you say PRINT LCASE$("MAÑANA"), the computer doesn’t know how to uncapitalize Ñ, so the computer prints:

maÑana

__Africa__ This program measures geographical emotions:

CLS

INPUT "What's the most exciting continent"; a$

IF a$ = "Africa" THEN

PRINT "Yes, it's the dark continent!"

ELSE

PRINT "I disagree!"

END IF

Line 2 asks:

What's the most exciting continent?

Line 3 checks whether the person’s answer is "Africa". If the person’s answer is "Africa", the computer prints "Yes, it’s the dark continent!"; otherwise, the computer prints "I disagree!"

But instead of typing "Africa", what if the person types "africa" or "AFRICA"? We still ought to make the computer print "Yes, it’s the dark continent!" Here’s how:

CLS

INPUT "What's the most exciting continent"; a$

IF UCASE$(a$) = "AFRICA" THEN

PRINT "Yes, it's the dark continent!"

ELSE

PRINT "I disagree!"

END IF

The new version of the IF statement says: if the person’s answer, after being capitalized, becomes "AFRICA", then print "Yes, it’s the dark continent!" So the computer will print "Yes, it’s the dark continent!" even if the person types "Africa" or "africa" or "AFRICA" or "AfRiCa".

__Yes/no questions__ Suppose you ask the person a yes-no question. If the person means "yes", the person might type "yes" or "Yes" or "YES" or "YES!" or just "y" or just "Y". So instead of saying —

IF a$ = "yes"

say this:

IF UCASE$(LEFT$(a$, 1)) = "Y"

That tests whether the first letter of the person’s answer, after being capitalized, is "Y".

Trim

Some folks accidentally press the SPACE bar at the beginning or end of a string. For example, instead of typing "Sue", the person might type " Sue" or "Sue ".

You want to get rid of those accidental spaces. Getting rid of them is called trimming the string.

The function LTRIM$ will left-trim the string: it will delete any spaces at the string’s beginning (left edge). For example, if a$ is " Sue Smith", LTRIM$(a$) is "Sue Smith".

RTRIM$ will right-trim the string: it will delete any spaces at the string’s end (right edge). If a$ is "Sue Smith ", RTRIM$(a$) is "Sue Smith".

To trim *both* edges of a$ and make the trimmed result be the new a$, say this:

a$ = LTRIM$(RTRIM$(a$))

Spaces at the string’s beginning (which are deleted by LTRIM$) are called leading spaces. Spaces at the string’s end (which are deleted by RTRIM$) are called trailing spaces.

Adding strings

You can add strings together, to form a longer string:

CLS

a$ = "fat" + "her"

PRINT a$

Line 2 says a$ is "father". The bottom line makes the computer print:

father

Searching in a string

You can make the computer search in a string to find another string. To make the computer search IN the STRing "needed" to find "ed", say:

PRINT INSTR("needed", "ed")

Since "ed" begins at the third character of "needed", the computer will print:

3

If you say —

PRINT INSTR("needed", "ey")

the computer will search in the string "needed" for "ey". Since "ey" is *not* in "needed", the computer will print:

0

If you say —

PRINT INSTR(4, "needed", "ed")

the computer will hunt in the string "needed" for "ed"; but the hunt will begin at the 4th character of "needed". The computer finds the "ed" that begins at the 5th character of "needed". The computer will print:

5

String-number conversion

This program converts a string to a number:

CLS

a$ = "52.6"

b = VAL(a$)

PRINT b + 1

Line 2 says a$ is the string "52.6". The next line says b is the numeric VALue of a$, so b is the number 52.6. The bottom line prints:

53.6

VAL converts a string to a number. The opposite of VAL is STR$, which converts a number to a string. For example, STR$(-7.2) is the string "-7.2". STR$(81.4) is the string " 81.4", in which the 8 is preceded by a space instead of a minus sign.

Repeating characters

Suppose you love the letter b (because it stands for big, bold, and beautiful) and want to print "bbbbbbbbbbbbbbbbbbbb". Here’s a short-cut:

PRINT STRING$(20, "b")

That tells the computer to print a string of 20 b’s.

Here’s a different way to accomplish the same goal:

PRINT STRING$(20, 98)

That tells the computer to print, 20 times, the character whose ASCII code number is 98.

STRING$ can make the computer repeat a single character, but not a whole word. So if you say STRING$(20, "blow"), the computer will *not* repeat the word "blow"; instead, the computer will repeat just the first character of "blow" (which is "b").

__Dashed line__ Let’s make the computer draw a dashed line containing 50 dashes, like this:

--------------------------------------------------

Here’s how: just say PRINT STRING$(50, "-").

__Triangle__ Let’s make the computer print this triangle:

*

**

***

****

*****

******

*******

********

*********

**********

***********

************

*************

**************

***************

****************

*****************

******************

*******************

********************

To do that, we want the computer to print 1 asterisk on the first line, then 2 asterisks on the next line, then 3 asterisks on the next line, and so on, until it finally prints 20 asterisks on the bottom line.

Here’s the program:

CLS

FOR i = 1 TO 20

PRINT STRING$(i, "*")

NEXT

The FOR line makes i be 1, then 2, then 3, and so on, up to 20. When i is 1, the PRINT line makes the computer print one asterisk, like this:

*

When i is 2, the PRINT line makes the computer print a line of 2 asterisks, like this:

**

The FOR line makes i be every number from 1 up to 20, so computer will print 1 asterisk, then underneath print a line of 2 asterisks, then underneath print a line of 3 asterisks, and so on, until the entire triangle is printed.

Trigonometry

The study of triangles is called trigonometry — and the computer can do it for you!

For example, look at this triangle:

In that triangle, the left angle is 30°, the bottom-right angle is 90°, and the longest side (the hypotenuse) is 1 inch long.

The side opposite the 30° angle is called the sine of 30°; the remaining side is called the cosine of 30°:

How long is the sine of 30°? How long is the cosine of 30°?

Since the longest side (the hypotenuse) is 1 inch long, and since the sine and the cosine are shorter sides, the sine and the cosine must each be shorter than 1 inch. So the lengths of the sine and cosine are each less than 1. But which decimals are they?

To find out, you can use a ruler. You’ll discover that the sine is half an inch long, and the cosine is nearly seven-eighths of an inch long. But a faster and more accurate way to measure the sine and cosine is to let the computer do it! Yes, the computer can calculate triangles in its mind!

This program makes the computer measure the sine and cosine of 30°:

CLS

degrees = ATN(1) / 45

PRINT SIN(30 * degrees)

PRINT COS(30 * degrees)

Line 2 is a special formula that defines the word *degrees*. The first PRINT line prints the sine of 30 degrees:

.5

The bottom line prints the cosine of 30°, which is a decimal that’s slightly less than .87.

The computer can measure the sine and cosine of *any* size angle. Try it! For example, to make the computer print the sine and cosine of a 33° angle, say:

CLS

degrees = ATN(1) / 45

PRINT SIN(33 * degrees)

PRINT COS(33 * degrees)

If you choose an angle of -33° instead of 33°, the triangle will dip down instead of rising up, and so the sine will be a negative number instead of positive.

In those PRINT lines, the "* degrees" is important: it tells the computer that you want the sine of 33 degrees. If you accidentally omit the "* degrees", the computer will print the sine of 33 radians instead. (A radian is larger than a degree. A radian is about 57.3 degrees. More precisely, a radian is 180/p degrees.)

Tangent

The sine divided by the cosine is called the tangent. For example, to find the tangent of 33°, divide the sine of 33° by the cosine of 33°.

To make the computer print the tangent of 33°, you could tell the computer to PRINT SIN(33 * degrees) / COS(33 * degrees). But to find the tangent more quickly and easily, just say PRINT TAN(33 * degrees).

Arc functions

The opposite of the tangent is called the arctangent:

the tangent of 30° is about .58

the arctangent of .58 is about 30°

Similarly, the opposite of the sine is called the arcsine, and the opposite of the cosine is called the arccosine.

This program prints the arctangent of .58, the arcsine of .5, and the arccosine of .87:

CLS

degrees = ATN(1) / 45

PRINT ATN(.58) / degrees

x = .5: PRINT ATN(x / SQR(1 - x * x)) / degrees

x = .87: PRINT 90 - ATN(x / SQR(1 - x * x)) / degrees

Line 3 prints the arctangent of .58, in degrees. (If you omit the "/ degrees", the computer will print the answer in radians instead of degrees.) Line 4 sets x equal to .5 and then prints its arcsine (by using a formula that combines ATN with SQR). The bottom line sets x equal to .87 and then prints its arccosine (by using a formula that combines 90 with ATN and SQR). The answer to each of the three problems is about 30 degrees.

Types of numbers

QBASIC can handle several types of numbers.

General rules

Here are the general rules about types of numbers. I’ll explain exceptions later.

__Real numbers versus integers__ If a number contains a decimal point, it’s called a real number. For example, 27.1 is a real number. So is -27.1. So is 27.0.

A number without a decimal point is called an integer. For example, 27 is an integer. So is -27. 27.0 is *not* an integer, since it contains a decimal point; 27.0 is a real number instead.

The computer handles integers faster than real numbers. To make your program run faster, use integers.

__Long integers versus short integers__ Tiny integers are called short integers. For example, 0, 1, and 2 are short integers. So is 27. So is 589.

The biggest permissible short integer is 32767. The lowest permissible short integer is -32768.

An integer that’s not short is called long. For example, 50000 is a long integer, since it’s an integer that’s bigger than 32767. Another long integer is -50000.

The biggest permissible long integer is 2147483647 (which is about 2 billion, using the American definition of *billion*). The lowest permissible long integer is -2147483648.

If you try to create an integer bigger than 2147483647, the computer will refuse. Instead, put a decimal point in the number, so the number becomes a real number. For example, if you want to deal with 5000000000, which is too big to be an integer, say 5000000000.0 instead, so the number is real.

The computer handles short integers faster than long integers, and handles long integers faster than real numbers.

To store a short integer in the computer’s RAM chips, the computer uses a special trick that lets the short integer fit into 2 bytes of RAM. So each short integer consumes just 2 bytes.

For example, 589 consumes just 2 bytes. 32767 consumes just 2 bytes. -32768 consumes just 2 bytes.

To store a long integer, the computer uses a different trick that consumes 4 bytes of RAM. For example, -2147483648 consumes 4 bytes of RAM.

__Single-precision versus double-precision__ A real number contains a decimal point. It can also contain a negative sign and lots of digits. If it contains at least 8 digits, it’s called a double-precision number.

For example, 725.14592 is a double-precision number, since it contains 8 digits. 2943423.0 is double-precision. So is .00000001. So are -52341523092342.31 and

-6.269549374523423, since each contains at least 8 digits. But .0000001 is *not* double-precision, since it contains just 7 digits.

A real number containing *fewer* than 8 digits is called single-precision. For example, .0000001 is single-precision. So is 5.2. So is -27.1.

A single-precision number can be up to 7 digits long. A double-precision number can be up to 16 digits long.

The computer handles single-precision numbers faster than double-precision.

A single-precision number consumes 4 bytes of RAM. A double-precision number consumes 8 bytes.

Suffix

At the end of a number, you can put a suffix:

__Suffix__ __Meaning__

% short integer

& long integer

! single-precision real

# double-precision real

For example, the number 27 is a short integer. If you want to turn it into a single-precision real, write "27.0" or "27!" instead of "27". If you want to turn it into a double-precision real, write "27.000000" or "27#". If you want to turn it into a long integer, write "27&".

__Automatic rewrite__ In your program, if you write a double-precision real, the computer will automatically put the symbol # afterwards when you press the ENTER key. For example, if you write —

PRINT 53926.175 * 27.000000

and then press the ENTER key, the computer will automatically turn your typing into this:

PRINT 53926.175# * 27#

If you write a single-precision real that ends in .0, the computer will automatically replace the .0 by "!". For example, if you write —

PRINT 200.0 * 300.0

and then press the ENTER key, the computer will automatically turn your typing into this:

PRINT 200! * 300!

Scientific notation

For single-precision real numbers, you can use E notation. For example, instead of writing 27945.86, you can write 2.794586E4. The "E4" means "move the decimal point 4 places to the right." Instead of writing .0006829, you can write 6.829E-4, in which the "E-4" means "move the decimal point 4 places to the left."

For double-precision real numbers, write a D instead of an E. For example, 2.794586D4 is the double-precision version of 2.794586E4.

The number before the E or D is called the mantissa; the number after the E or D is called the exponent. For example, in the number 2.794586E4, the mantissa is 2.794586; the exponent is 4.

For a single-precision numbers, the mantissa can contain up to 7 digits. For double-precision numbers, the mantissa can contain up to 16 digits.

A number that contains a D is double-precision, even if the mantissa contains few digits or no decimal point. A number that contains an E is single-precision, even if the mantissa contains no decimal point; but if the mantissa contains more than 7 digits, the computer will turn the E into a D when you press ENTER.

Biggest real numbers

The biggest permissible single-precision number is about 3.000000E38. More precisely, it’s 3.402823E38.

The biggest permissible double-precision number is about 1.000000000000000D308. More precisely, it’s 1.797693134862315D308.

If you try to go higher than those numbers, the computer will gripe by saying "Overflow".

Accuracy

The computer handles integers accurately. The computer *tries* to handle real numbers accurately but sometimes makes slight mistakes with the real number’s last digit.

For a single-precision real number, the computer makes slight mistakes with the 7^{th} digit. For a double-precision real number, the computer makes slight mistakes with the 16^{th} digit.

Tiniest decimals

You’ve seen that the biggest permissible double-precision number is about 1D308. The tiniest double-precision decimal that the computer can handle well is about 1D-308. If you try to go much tinier, the computer will usually botch the last few digits of the number (and replace those digits by different digits instead!) or else round the entire number to zero.

You’ve seen that the biggest permissible single-precision number is slightly bigger than 1E38. The tiniest single-precision decimal that the computer can handle well is about 1E-38. If you try to go much tinier, the computer will usually botch the last few digits of the number (and replace those digits by different digits instead!) or else round the entire number to zero.

Variables

Usually, each ordinary variable (such as x) stands for a single-precision real number. For example, you can say x=3.7, which makes x be the single-precision number 3.7.

If you say x=3, the computer will make x be 3.0 instead, to make x be a single-precision number. Though the screen will still say x=3, the x box in the computer’s RAM will contain 3.0 instead.

You can create five kinds of variables:

A variable that’s ordinary (such as x) or ends in an exclamation (such as x!) is single-precision real.

A variable that ends in a dollar sign (such as x$) is a string.

A variable that ends in a percent sign (such as x%) is an short integer.

A variable that ends in an ampersand (such as x&) is a long integer.

A variable that ends in a number sign (such as x#) is double-precision real.

If you begin your program by saying —

DEFINT A-Z

all ordinary variables (such as x) will be short integers instead of single-precision real. (The word "DEFINT" means "DEFine to be INTegers".) If instead you say —

DEFLNG A-Z

all ordinary variables will be LoNG integers. If instead you say —

DEFDBL A-Z

all ordinary variables will be DouBLe-precision real.

What to do

Write your program simply, without worrying about which numbers and variables are short integers, long integer, single-precision real numbers, and double-precision real numbers. But after your program is written and you’ve removed any errors, edit the program by making the following changes, which improve the program’s speed and accuracy.

__All short integers__ If your program doesn’t involve any decimals or big numbers, make the top line say DEFINT A-Z. That will turn every variable into a short integer, so the program runs faster and consumes less RAM.

__Mostly short integers__ If your program involves just a *few* decimals or big numbers, make the top line say DEFINT A-Z; then put an exclamation point (!) after every variable standing for a decimal, and put an ampersand (&) after every variable standing for a long integer.

__Extra accuracy__ If you want to perform one of the computations extra-accurately, put a number sign after every variable the computation involves. For example, say x# instead of x.

Also, make sure that each number in the computation contains a number sign or at least 8 digits. For example, instead of saying 2.4, say 2.4# or 2.4000000.

Avoid round-off errors

The computer cannot handle decimals accurately. If you say x=.1, the computer can’t set x equal to .1 exactly; instead, it will set x equal to a number very, very close to .1. The reason for the slight inaccuracy is that the computer thinks in "binary", not decimals; and .1 can*not* be expressed in binary exactly.

Usually you won’t see the slight inaccuracy: when you ask the computer to PRINT a number, the computer prints it rounded to six significant figures, and the inaccuracy is so small it doesn’t show up in the rounded result. But there are three situations in which the inaccuracy can be noticed:

1. You’ll get wrong digits if you make the computer do x minus y, where x is almost equal to y (so the first several digits of x are the same as the first several digits of y). For example, if you say —

PRINT 8.1 - 8

the computer will print .1000004 instead of .1. The same thing happens if you say:

PRINT 8.1 + (-8)

If you say —

PRINT 80000.1 - 80000

the computer will print .1015625 instead of .1.

If you say —

PRINT 800000.1 - 800000

the computer will print .125 instead of .1.

The error can get magnified: if you ask the computer to multiply 800000.1-800000 by 1000, it will print .125*1000, which is 125, instead of .1*1000, which is 100. If you ask it to find the reciprocal of 800000.1-800000, it will print 1/.125, which is 8, instead of 1/.1, which is 10.

2. You’ll get wrong looping if you say "FOR x = a TO b STEP c", where c is a decimal and the loop will be done many times. For example:

FOR x = 1 TO 2 STEP .1

PRINT x

NEXT

Theoretically, the computer should print 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, and 2. But that’s not what actually happens. In the FOR line, the computer can’t handle the decimal .1 accurately. The last few numbers the computer thinks of are:

slightly more than 1.7

slightly more than 1.8

slightly more than 1.9

The computer does *not* think of the next number, slightly more than 2.0, because the FOR line says not to go past 2. The PRINT line makes the computer print the numbers rounded to seven significant digits, so it prints:

1

1.1

1.2

1.3

1.4

1.5

1.6

1.7

1.8

1.9

It does not print 2.

If you want to compute 1 + 1.1 + 1.2 + 1.3 + 1.4 + 1.5 + 1.6 + 1.7 + 1.8 + 1.9 + 2, you might be tempted to write this program:

CLS

s = 0

FOR x = 1 TO 2 STEP .1

s = s + x

NEXT

PRINT s

The computer will print a reasonable-looking answer: 14.5. But the computer’s "answer" is wrong, since the last number the computer added was slightly more than 1.9; it never added 2. The correct answer is 16.5.

To fix those FOR loops, you can change the FOR line to this

FOR x = 1 TO 2.05 STEP .1

The .05 after the 2 allows for the margin of error. The general strategy is to change —

FOR x = a TO b STEP c

to this:

FOR x = a TO b + c / 2 STEP c

An alternative fix is to replace —

FOR x = 1 TO 2 STEP .1

by this pair of lines:

FOR i = 10 TO 20

x = i / 10

As i goes from 10 to 20, x will go from 1 to 2 in steps of .1. This fix is the most accurate of all, since it eliminates decimals from the FOR line. But the new indented line (x = i / 10) makes the program run very slowly, since that line requires the computer to perform division, and the division is performed repeatedly (since it’s in the FOR loop).

3. You’ll get wrong testing if you ask the computer whether two numbers x and y are equal. It’s unwise to ask whether x is *exactly* equal to y, since both x and y have probably been affected by some slight error. Instead, ask the computer whether the difference between x and y is much tinier than y:

__Bad__ __Good__

IF x = y THEN IF ABS(x - y) <= .000001 * ABS(y) THEN

The .000001 is requesting that the first six significant digits of x be the same as the first six significant digits of y (except that the sixth significant digit might be off by one).

__Why binary?__ From those discussions, you might think computers should be made differently, and that they should use the decimal system instead of binary. There are two counterarguments.

First, binary arithmetic is faster.

Second, even if computers were using the decimal system, inaccuracy would still occur. To store the fraction 2/3 accurately by using the decimal system, the computer would have to store a decimal point followed by infinitely many 6’s. That would require an infinite amount of space in memory, which is impossible — unless you know how to build an infinitely large computer? So even in the decimal system, some fractions must be approximated instead of handled exactly.

__Begin with the tiny__ According to mathematicians, addition is supposed to obey these laws:

x+0 is exactly the same as x

x+y is exactly the same as y+x

x+-x is exactly the same as 0

(x+y)+z is exactly the same as x+(y+z)

On the computer, the first three laws hold, but the last does not. If x is a decimal tinier than z, the computer does (x+y)+z more accurately than x+(y+z). So to add a list of numbers accurately, begin by adding together the tiniest decimals in the list.

Integer division

When you add, subtract, or multiply integers together, the answer is an integer:

11 + 4 is an integer, 15

11 - 4 is an integer, 7

11 * 4 is an integer, 44

When you divide integers by using a slash (/), the answer is a real number:

11 / 4 is a real number, 2.75

__Backslash__ If you divide integers by using a backslash (\), the computer will ignore any decimal digits and give you just an integer:

11 \ 4 is an integer, 2

__Remainder__ When you divide 11 by 4, the remainder is 3:

__ 2__

4 ) 11

__-8__

3 is the remainder

If you ask for 11 MOD 4, the computer will tell you the remainder when you divide 11 by 4:

11 MOD 4 is an integer, 3

So if you say —

PRINT 11 MOD 4

the computer will print:

3

Prime numbers

An integer is called composite if it’s the product of two other integers:

35 is composite because it’s 5 * 7

9 is composite because it’s 3 * 3

12 is composite because it’s 2 * 6

13 is *not* composite, so it’s called prime

This program tells whether a number is prime or composite:

CLS

DEFLNG A-Z

INPUT "What's your favorite positive integer"; n

FOR i = 1 TO n - 1

FOR j = 1 TO n - 1

IF n = i * j THEN PRINT n; "is"; i; "times"; j; "and composite": END

NEXT

NEXT

PRINT n; "is prime"

To make the program run faster, we want all variables to be integers instead of reals. To let the program handle *big* numbers, we want the integers to be long. The DEFLNG line accomplishes all that: it makes all variables be long integers.

Here’s how the program works. The INPUT line waits for you to type an integer n. The IF line checks whether n is the product of two other integers; if it is, the computer says n is composite.

How fast does that program run? If n turns out to be prime, the IF line is encountered once for every i and once for every j; altogether it’s encountered (n-1)2 times. If n is a big number, around a billion, (n-1)2 is around a quintillion. (I’m using the American definitions of billion and quintillion. An American billion is 1,000,000,000; an American quintillion is 1,000,000,000,000,000,000. British definitions of billion and quintillion are different.) To do the IF line a quintillion times will take a typical microcomputer many years. For example, if you say that your favorite number is 999999929 (which is close to a billion), the typical 486DX2-66 computer will take about *400,000 years* before it comes to the conclusion that your number is prime! By the time the program finishes running, you’ll be dead and so will many generations of your decendents! Probably your computer or its electricity will have died by then too! The program’s very slow.

Some small improvements are possible; for example, i and j can start at 2 instead of 1. But so long as you have a loop inside a loop, the time will remain very huge.

The following strategy requires just one loop: divide n by every integer less than it, to see whether the quotient is ever an integer. Here’s the program:

CLS

DEFLNG A-Z

INPUT "What's your favorite positive integer"; n

FOR i = 2 TO n - 1

IF n MOD i = 0 THEN PRINT n; "is divisible by"; i; "and composite": END

NEXT

PRINT n; "is prime"

The IF line makes the computer divide n by i, compute the remainder (which is called "n MOD i"), and check whether that remainder is 0. If the remainder is 0, then n divided evenly by i, so n is divisible by i, so n is composite.

How fast is our new program? If n turns out to be prime, the IF line is encountered once for every i; altogether it’s encountered n-2 times. That’s less than in the previous program, where it was encountered (n-1)2 times. If n is about a billion, our new program does the IF line about a billion times, which is much fewer than the quintillion times required by the previous program! It’s nearly a billion times faster than the previous program! To determine whether 999999929 is prime, the new program takes a 486DX2-66 computer about 5 hours instead of 400,000 years.

We can improve the program even further. If an n can’t be divided by 2, it can’t be divided by any even number; so after checking divisibility by 2, we have to check divisibility by just 3, 5, 7, …, n-2. Let’s put that short-cut into our program, and also say that every n less than 4 is prime:

CLS

DEFLNG A-Z

INPUT "What's your favorite positive integer"; n

IF n < 4 THEN PRINT n; "is prime": END

IF n MOD 2 = 0 THEN PRINT n; "is divisible by 2 and composite": END

FOR i = 3 TO n - 2 STEP 2

IF n MOD i = 0 THEN PRINT n; "is divisible by"; i; "and composite": END

NEXT

PRINT n; "is prime"

Line 5 checks divisibility by 2; the FOR loop checks divisibility by 3, 5, 7,… , n-2. If n is prime, the indented IF line is encountered n/2 - 2 times, which is about half as often as in the previous program; so our new program takes about half as long to run. On a 486DX2-66 computer, it takes about 2½ hours to handle 999999929.

Our goal was to find a pair of integers whose product is n. If there is such a pair of integers, the smaller one will be no more than the square root of n, so we can restrict our hunt to the integers not exceeding the square root of n:

CLS

DEFLNG A-Z

INPUT "What's your favorite positive integer"; n

IF n < 4 THEN PRINT n; "is prime": END

IF n MOD 2 = 0 THEN PRINT n; "is divisible by 2 and composite": END

FOR i = 3 TO SQR(n) * 1.000001 STEP 2

IF n MOD i = 0 THEN PRINT n; "is divisible by"; i; "and composite": END

NEXT

PRINT n; "is prime"

The "1.00001" is to give a margin of safety, in case the computer rounds SQR(n) a bit down. If n is near a billion, the indented IF line is encountered about 15,000 times, which is much less than the 500,000,000 times encountered in the previous program and the 1,000,000,000,000,000,000 times in the original. This program lets a 486DX2-66 computer handle 999999929 in about ¼ of a second. That’s much quicker than earlier versions, which required 2½ hours, or 5 hours, or 400,000 years!

Moral: a few small changes in a program can make the computer take ¼ of a second instead of 400,000 years.

The frightening thing about this example is that the first version we had was so terrible, but the only way to significantly improve it was to take a totally fresh approach. To be a successful programmer, you must always keep your mind open and hunt for fresh ideas.