Chapter Six
Input Range Testing, Tolerances
KeyWord: BEEP

This chapter will start us off by learning how to check data that was input by an operator using an INPUT statement. Let's assume that you have a program that requires the user to input a positive number, and that zero can be allowed. What happens if the user enters in a negative number? How do you check it, and how can you correct it? Let's find out! Here is a section of program code that has our input checking property:

```
...

GETNUM:

PRINT "Enter a positive number";

INPUT A

IF A >= 0 THEN GOTO NUMOK

PRINT "You have entered a negative number! Try again"

GOTO GETNUM

NUMOK:

LET X=2*(A/D)

...```

Let's trace through this program section to see what it does. When the program gets to the second line, it prints out the message indicating what the user needs to do. Line 3 then prints a question mark on the screen and waits for the user to type in a number. When the user enters the number, it gets assigned to the variable A, and the program continues to line 4. Here we have one of those wonderful IF...THEN commands. What it does is check the value of A to see if it is greater than or equal to (remember those from chapter 2?) zero. If it is, we have a valid response and the program jumps to line 7. If not, the program drops down to line 5 and prints out the "now look what you did" message. Then line 6 tells us to go to line 1, where the user is again asked to enter the positive number, and we do it all over again.

Now we get to write a "really neat" program. It actually calculates square roots. The method that is used is called "divide and average", and it works like this. Take the number you want to find the square root, and divide it by some arbitrary number. In our case, we'll divide it by 2. Now we take that answer, and divide the original number by it. Now we average the first answer with the new answer, and divide the original number by that result. We now take what we get and average it with the answer we got before. We continue this crazy cycle until the two answers are identical, in which case we will have the square root. Let's run through it using a real number so that you can understand what on earth is going on around here. We'll use 16 since it's a perfect square.

Take the 16 and divide it by 2. You get 8. Now take the 16 and divide it by the 8, and you get 2. Now average the 2 and the 8 to get 5. Now we divide the 16 by 5 and get 3.2. We average our new answer of 3.2 with our old answer of 5 to get 4.1. Now we divide 16 by 4.1 to get (approximately) 3.9. Now we average the 3.9 and the 4.1 to get 4. Now divide 16 by 4 to get 4. Since the new answer and the previous average are the same, we have arrived at the square root. Let's put that into QBASIC. We will start out by asking for a number, so our first lines will be PRINT and INPUT commands to get a number. Be sure to clear out any program that is in memory:

```

PRINT "Enter Number to Find Square Root";

INPUT NUM```

You will notice that we have to keep track of two answers. We will refer to them as new answer and old answer. We'll use the somewhat descriptive variable names NEWANS and OLDANS to keep track of them:

```

LET OLDANS = NUM / 2

```
Next, we divided the original number by the old answer to get a new answer. We will also need a label here for our loop. We'll use an abbreviation of "Calculate Answer" without spaces (you can't have spaces in label names).
```

CALCANS:

LET NEWANS = NUM / OLDANS```

Next, we average the two answers together.

```

LET OLDANS = (NEWANS + OLDANS) / 2```

After that, we go back and do it again.

```

GOTO CALCANS```

Now, we need to check when the answers are the same. We'll do that right after we do the division, so insert this line right after the LET OLDANS= line:

```

IF NEWANS = OLDANS THEN GOTO FINISHED```

When we finally get the answer, all we have to do is print it out and end the program. Add this to the bottom of the program:

```

FINISHED:

PRINT "Square Root Of "; NUM; " Is"; NEWANS

END```

Just to make sure you have it in right, here's what we have so far:

```
PRINT "Enter Number to Find Square Root";

INPUT NUM

LET OLDANS = NUM / 2

CALCANS:

LET NEWANS = NUM / OLDANS

LET OLDANS = (NEWANS + OLDANS) / 2

IF NEWANS = OLDANS THEN GOTO FINISHED

GOTO CALCANS

FINISHED:

PRINT "Square Root Of "; NUM; " Is"; NEWANS

END```

`IF NEWANS = OLDANS THEN GOTO FINISHED`

with:

```

IF ABS(NEWANS - OLDANS) < .00001 THEN GOTO FINISHED```

Now if you run the program, it will work fine. Notice that we took the absolute value of the difference? That way, we would get a positive result no matter which way the numbers are. If the difference of these two numbers is less than 0.00001, a really really really small number, then we will assume that they are the same. However, there is a minor flaw with this method. As we find the square roots of larger numbers, the tolerance become apparently much smaller, because the answers are bigger. For huge numbers, say 30 digit numbers, we may still get the computer to lock up. We could use a slightly bigger number on the right side of the less-than sign, but that would reduce the accuracy of the result for the smaller answers. So how do we fix that? We can make the tolerance change by not using an actual number, but instead by using a percentage of the original number. This will make the tolerance very tight for small numbers, and loosen it for huge numbers. To do that, we simply multiply our original number by a small constant. The corrected line will look like this:

```

IF ABS(NEWANS - OLDANS) < .00001 * NEWANS THEN GOTO FINISHED```

Now the answer will be within .001% of the original number. That's pretty accurate, isn't it? There is still a major problem with the program. Run it again, and try to find the square root of -16. Oh, look! Another coffee break! Why? Each time it finds a new answer, the sign changes! First positive, then negative, then positive again, and so on. It will never zero in on a number but jump around wildly as it tries to average a positive and negative number. If the two numbers are close, but one is positive and the other negative, it will average out to be close to zero. When you divide a number by another very small number, you get a very large answer, and then it will average the new large answer with the old small number. How do we stop this? We don't let the user enter a negative number. How? We showed you at the beginning of the chapter. See if you can figure it out first, but first notice that entering a zero will also give you a "Division by zero" error - we don't want that, either.

Here is the program segment you need to enter to do the job. Between the lines
INPUT NUM
LET OLDANS = NUM / 2

enter:

```

IF NUM > 0 THEN GOTO ENTEREDOK

BEEP

PRINT"Number must be greater that zero - Try again"

GOTO TOP

ENTEREDOK:```

```

TOP:```

Whoa! Look at the line that says "BEEP"! what does that do? What do you think it might do? Would you like to find out? Then type in BEEP in the immediate window and listen closely! To be completely technical, it produces an 800 Hz tone for 0.27 seconds. In real English, it makes the computer beep. I guess in this case you could call it an error alarm! It alerts the user that he has made an input error, and is accompanied by the "nice going, stoopid!" message. The user is then allowed to try again.

Just to make sure you have everything typed in correctly, here is the program in it's entirety:

```

TOP:

PRINT "Enter Number to Find Square Root";

INPUT NUM

IF NUM > 0 THEN GOTO ENTEREDOK

BEEP

PRINT "Number must be greater that zero - Try again"

GOTO TOP

ENTEREDOK:

LET OLDANS = NUM / 2

CALCANS:

LET NEWANS = NUM / OLDANS

LET OLDANS = (NEWANS + OLDANS) / 2

IF ABS(NEWANS - OLDANS) < .00001 THEN GOTO FINISHED

GOTO CALCANS

FINISHED:

PRINT "Square Root Of "; NUM; " Is"; NEWANS

END```

If you want to see the intermediate answers, add the program line that's in color:

```
TOP:

PRINT "Enter Number to Find Square Root";

INPUT NUM

IF NUM > 0 THEN GOTO ENTEREDOK

BEEP

PRINT "Number must be greater that zero - Try again"

GOTO TOP

ENTEREDOK:

LET OLDANS = NUM / 2

CALCANS:

LET NEWANS = NUM / OLDANS

LET OLDANS = (NEWANS + OLDANS) / 2

IF ABS(NEWANS - OLDANS) < .00001 THEN GOTO FINISHED

GOTO CALCANS

FINISHED:

PRINT "Square Root Of "; NUM; " Is"; NEWANS

END```

That's all for this time, but here are some programs for you to try your hand at:

INPUT a three digit number, and print it's reversal. In other words, given 275, print 572. You will need input range checking for this program to work. An original number ending with zero (420) can be printed out without leading zeros (24 is okay, since the computer won't print 024). If you would prefer, you may print it out as a three-digit number (024), but the PRINT command will automatically put spaces between each number (that's okay). HINT: Use division and either the INT(x) or FIX(x) functions.

INPUT a four digit number and print its reversal. In other words, given 9371, print 1739. Use the same hint as above.

Given a positive number less that 20,000, (Use INPUT and error checking) determine if it is a prime number. A prime number can be divided evenly only by 1 and itself. A word of caution here. On the lower speed computer, the larger numbers (over 10,000) can take over a minute to calculate.

Next chapter, we will learn about random number generation, and talk about a major problem: storing large amounts of data in variables. See you next time!!

Introduced In This Chapter:
Keyword: BEEP

Concepts: Input range checking, tolerance, audible signaling.