QUICKBASIC/QBASIC TUTORIAL RE: ALGORITHMS
=========================================
By Edward F. Moneo

TABLE OF CONTENTS:
-----------------
1.  INTRODUCTION 
2.  DETERMINE IF A NUMBER IS A POWER OF 2
3.  GENERATE A GRAY CODE PATTERN
4.  COMPUTE THE NEXT MULTIPLE
5.  COMPUTE THE NEAREST MULTIPLE
6.  ROUNDING NUMBERS
7.  INPUT ONE AND ONLY ONE CHARACTER
8.  REPRESENT A NUMBER AS BINARY BITS
9.  BIT OPERATIONS
10. CENTIGRADE/FAHRENHEIT CONVERSION
11. GENERATE A RANDOM NUMBER
12. EUCLID'S ALGORITHM FOR GREATEST COMMON DIVISOR


1. INTRODUCTION

   The following is a collection of algorithms or proven methods for solving
   common problems. Before you incorporate any of these into your programs,
   it is recommended that you fully understand the code, and that you test
   the algorithm with the range of numbers that you intend using. You will
   notice that for the most part, with few indicated exceptions, there are
   no type declarations on the variables used, and therefore, as a default,
   integer variables are assumed, and the logic has been tested using integers.
   Also, with few indicated exceptions, the variables are assumed to be
   positive numbers.

   It is important to note that many of the following algorithms were
   chosen as the best available under intensive scrutiny and testing by
   members of the Qbasicnews and QBNZ forums.

   NOTE: Credit is given for code developed by other programmers. If no
         credit is indicated, the code was developed by the author.


2. DETERMINE IF A NUMBER IS A POWER OF 2:
   CREDIT: Xhantt of Qbasicnews.
   GIVEN: N is the positive number in question.
   LOGIC: When you AND a number which is a power of 2
          with the number-1, which would be all 1 bits,
          then if the result is zero (because no other bits were found),
          then the number must be a power of 2.

   if (N>0) and ((N and (N-1))=0) then print N; " is a power of 2" 


3. GENERATE A GRAY CODE PATTERN:
   CREDIT: author unknown
   Gray Code, named after Frank Gray of Bell Labs, is a series of bytes
   or words where each byte/word in the series differs from the preceding
   BY ONLY ONE BIT. Example:  0, 1, 3, 2, 6, 7. These patterns have been
   used for testing logic circuits, communication transmissions, etc.

   GIVEN: Generate a Gray Code pattern for values from 0 to 255.

   for x=0 TO 255
        GRAY = x XOR (INT(x/2))
        rem ...Here you print or output successive Gray Code values in GRAY.
   next x


4. COMPUTE THE NEXT MULTIPLE:
   GIVEN: Given a positive number N, compute the NEXT multiple of X.
          Result to R.
   EXAMPLE #1: Given 47, compute the next multiple of 5, which is 50.
   EXAMPLE #2: Given 50, compute the next multiple of 5, which is 55.

   R = int((N+X)/X)*X


5. COMPUTE THE NEAREST MULTIPLE:
   GIVEN: Given a positive number N, compute the NEAREST multiple of X.
          Result to R.
   Note:  Nearest multiple means that if N is already a multiple of X,
          don't move up to next multiple. This is kind of like rounding;
          e.g., round to nearest $5. If already $5, leave it alone.
   EXAMPLE #1: Given 47, compute the nearest multiple of 5, which is 50.
   EXAMPLE #2: Given 50, compute the nearest multiple of 5, which is 50.

   R = int((N+X-1)/X)*X


6. ROUNDING NUMBERS (POSITIVE OR NEGATIVE):
   CREDIT: Oracle of Qbasicnews and QBNZ.
   The purpose is to round positive or negative numbers to the nearest whole
   number. The standard convention of "half-adjusting" by a rounding factor of
   .5 is used. Notice that positive numbers must be rounded up, and negative
   numbers are rounded down, that is, to a greater negative number.

   NOTE: If you do INT(123.9) you will get 123. However, if you do INT(-123.9)
         you will get -124. This is the documented method of how the INT works
         in QB, which in the case of the INT(-123.9), is NOT what we want,
         since we want -123.

   The following code takes the above conditions into consideration. 
   * The absolute or ABS assures that the number to work with is positive. 
   * This positive number is rounded by the rounding factor of "+.5".
   * The integer value INT is taken on the above positive result.
   * The sign of the original input number is restored by multiplying by the
     sign or SGN which is 1 for positive, -1 for negative, and 0 for zero.

   GIVEN:
   * N is the number to be rounded. Obviously, since it can have decimals,
     it must have a type declaration of single or double floating point.
     We will define it as single (!) for this example.
   * R will be the resultant rounded whole number.

   R = SGN(N!) * INT(ABS(N!) + .5) 


7. INPUT ONE AND ONLY ONE CHARACTER:
   GIVEN: With the following routine, we want to input only one character,
          and if the user enters more than one character, we want to get rid
          of the extra characters.
          We get rid of the extra characters in order that they will not be
          processed later by any code performing an input or an inkey$.
          Example: If we ask the user for a yes/no answer and prompt him to
          enter Y or N, he could by error type in NO. If we don't get rid
          of the extra O, then it will be given as input to the next prompt.
          * Input the one character into TheKey$

    DO
      TheKey$=INKEY$ 
    LOOP WHILE TheKey$="" 
    WHILE INKEY$<>"":WEND 
 

8. REPRESENT A NUMBER AS BINARY BITS:
   GIVEN: Assume N is from 0 to 255; that is, 8 bits.

   zbin$="00000000"
   for X = 0 to 7
       if (N and 2^X) then mid$(zbin$,(X xor 7)+1,1)="1"
   next X
   print zbin$

   8a. A similar approach:
       CREDIT: Francisco Moneo of ITAM University.

   DIM BIN AS LONG
   BIN=0
   FOR X=0 TO 7
       IF (N AND 2^X) THEN BIN=BIN+10^X
   NEXT X
   PRINT RIGHT$("00000000"+LTRIM$(STR$(BIN)),8)


9. BIT OPERATIONS:
   Here are some useful bit operations:

   9a. Flip a switch that has a zero or one value.
    
   switch = switch xor 1

   9b. Another method to flip a switch that has a zero or one value.
       CREDIT: WhiteTiger0990 of Qbasicnews.
    
   switch = 1 - switch

   9c. Yet another method to flip a switch that has a zero or one value.
       This works, but it's tricky. Note that the expression switch=0
       will evaluate as true (-1) or false (0) before performing the AND 1.
       CREDIT:Oracle of Qbasicnews and QBNZ.

   switch = (switch = 0) AND 1 

   9d. Flip a switch that has a zero (false) or minus one (true) value.
    
   switch = not(switch)

   9e. NOTE: When testing a switch that has a zero or one value,
       you must specify the complete expression when doing an IF.

       if switch = 1 then goto swon  'This is correct
       if switch = 0 then goto swoff 'This is correct

       if switch then goto swon      'This is not correct

   9f. NOTE: When testing a switch that has a zero (false)
       or a minus one (true) value, you must may test the switch as follows:

       if switch then goto swon       'This is correct
       if not(switch) then goto swoff 'This is correct
       if switch = -1 then goto swon  'This is also correct
       if switch = 0 then goto swoff  'This is also correct

       The recommended and more explicit way of handling switches
       with zero (false) and minus one (true) is as follows:

       CONST FALSE = 0            ' 0
       CONST TRUE  = NOT(FALSE)   ' -1

       if switch = TRUE then goto swon  
       if switch = FALSE then goto swoff 

   9g. Perform an XOR without using the XOR operator.
       GIVEN: Perform the equivalent of a XOR b.

   result = (a and not(b)) or (b and not(a))


10. CENTIGRADE/FAHRENHEIT CONVERSION:
   GIVEN: Convert Centigrade degrees in C# to Fahrenheit degrees in F#.

   F# = 9/5*C# + 32

   GIVEN: Convert Fahrenheit degrees in F# to Centigrade degrees in C#.
   
   C# = 5/9*(F# - 32)


11. GENERATE A RANDOM NUMBER:
    GIVEN: Generate a random integer greater than or equal to the LOWER
           parameter and less than or equal to the UPPER parameter.
 
   RANDOMIZE TIMER  'Seed the random number generator 
                    '(You must do this at the beginning of your program)

   RandInt% = INT(RND * (UPPER - LOWER + 1)) + LOWER


12. EUCLID'S ALGORITHM FOR GREATEST COMMON DIVISOR:
    CREDIT: Donald E. Knuth's book "The Art of Computer Programming,
            Volume 1: Fundamental Algorithms".
    GIVEN: Find the GREATEST common divisor for two non-zero,
           positive numbers M and N.

    IF M<N THEN SWAP M,N
    DO
        R=M MOD N
        IF R=0 THEN EXIT DO
        M=N
        N=R
    LOOP         
    PRINT "Greatest common divisor = ";N

*****


