Authors
Publication
Pub Details
Date
Pages
BASIC Terms
“When I use a word”, Humpty Dumpty said in rather a scornful tone, “it means just what I choose it to mean—neither more nor less.”
“The question is”, said Alice, “whether you can make words mean so many different things.”
“The question is”, said Humpty Dumpty, “which is to be master, that’s all.”
— Lewis Carroll’s Through the Looking Glass
In the last two parts of this discussion, we’ve seen that the computer is master when it comes to interpreting numbers; if it chooses to ignore reality, there’s nothing that we can do about it. Our only defense is to be aware of the computer limitations and avoid them however we can. If we don’t, the results can be just as mad as the things Alice saw behind the looking glass or down the rabbit hole.
One cause of the “BRICK WALL” is the fact that the computer uses only a limited number of digits to express a number. Any extra digits in a result just get “chopped off”. Last time we saw that changing the order of a multiplication and division could determine whether or not the two numbers were interpreted as equal. Since that could determine the outcome of a program, it’s a concern. With that in mind, let’s define:
Brick Wall Rule Number 1:
Avoid using = or < > with numbers in an IF statement. [It’s OK for strings].
If you only use integers, and then only do adds, subtracts, or multiplies [no divides!] you can probably ignore this rule. Ignoring it in any other case could be trouble. Instead of saying IF A=B THEN … you might say IF ABS(A-B)<.0001 THEN… which not only passes if A=B, but also if A and B are within .0001 of one another. You can, of course, modify this for whatever tolerance you need.
Interestingly enough, the problem we did last time only “fouled up” the TS1000, not the TS2068. The TS2068 already has a small tolerance built into it, but it’s not hard to find instances where this “fix” causes problems of its own. First, let’s look at a case that will confound both machines.
In the first part of the series we found that:
1 FOR J=10000000000 TO 10000000010 STEP 2
2 NEXT J
runs in a flash, but if we change the STEP 2 into STEP 1 it runs forever [on both machines]. In decimal, the machine can fairly accurately represent numbers that are about 10 digits long. If we go too much larger, the less significant part is just chopped off. The numbers in our FOR/NEXT loop are 11 digits long, and are in the “danger” zone. The number 2 is just barely large enough to be added to those numbers without being chopped off; the number 1 is not. Thus, adding 1 gives the same result as adding 0, which means that the final count is never reached. This brings us to:
Brick Wall Rule Number 2:
Be careful when you mix very large and very small numbers.
The next problem can demonstrate both the “round off” error in the TS2068 that we already did for the TS1000, and also a new problem, not seen before. For either machine, ENTER:
10 LET A=1
20 LET B=A
30 LET C=4
40 FOR J=1 TO C
50 LET A=A/3
60 NEXT J
70 FOR J=1 TO C
80 LET A=A*3
90 NEXT J
100 PRINT A,B
110 IF A=B THEN PRINT "EQUAL"
120 IF A<>B THEN PRINT "NOT EQUAL"
What the program does is divide 1 by 3, four times, and multiplies it back by 3, four times. Mathematically, A still equals B in the end. Running it gives us “1 1 EQUAL” as a result. So far so good.
Now let’s foul up the 2068. Change line 30 to LET C=5, and satisfy yourself that this shouldn’t change the result. We simply multiply and divide 5 times, instead of 4. The multiplies and divides should still cancel, and A should still equal B at the end. If this is run on the TS1000 the result will be “1 1 EQUAL”, which is correct. A TS2068 will give “1 1 NOT EQUAL”. Notice that it rounded A up to 1 and printed it on the screen, even though it is slightly less than 1 in the machine. Here’s an instance where the 2068 gives a round-off error more easily than the TS1000! The reason for the error is the round-off type, like we demonstrated last time on the TS1000, but not the 2068! Now we’ve evened the score!
The program becomes more interesting though, when we change line 30 to LET C=100. This time, for either machine, the result is “0 1 NOT EQUAL”. I think we can agree that “0” is not equal to “1”, but how did A get to be 0? In lines 40 through 60 we did 100 occurances of dividing A by 3. This is the equivalent to dividing A by 3 to the 100th power. Although it’s not obvious because the program uses fairly small numbers, this is just a bit larger than 5 followed by 47 zeros. This is a very lage number and dividing A by it produces a very small number. Since the computer uses only a limited number of digits, the best it can do is to select a number that’s close to the answer. In this case the quotient is rounded down to zero. Then, in lines 70 through 90, when we try to compensate by multiplying by 3 to the hundredth power, we get no satisfaction, because multiplying anything times zero still gives us zero. There’s that old brick wall again! This is really a violation of rule number 2, but it is so subtle that it deserves a new rule:
Brick Wall Rule Number 3:
If possible, arrange the order of your program steps to keep your variables from changing any more widely than they have to.
In this case, we could have alternated the multiplies and divides. It would not only have simplified the program, but A would never have gotten less than about 1/3. It may not have given us equal as a result, but if we applid RULE NUMBER 1, we could have fixed that, as well. If we try to apply all of the rules at once, the proram works.
This pretty much conclues my dicussion on computer number resolution and limits as they apply to our machines. It is by no means complete; it merely serves as a starting point for those who are interested in accurate programs [and who don’t like suprises!]. For those who have followed this series to the end and would like to know more, I’ll be glad to discuss the subject with you at any SINCUS meeting. In the meantime, I hope my 3 “RULES” might help to make life just a bit easier.