'============================================================================ ' G.H. George 1989 DEC 12 ' BASECONV.BAS modified 1998 MAY 13 ' Convert a decimal number to any base from 2 to 62 . '============================================================================ ' Subprograms / Functions: ' AskFor: ask the user to supply a new number and/or new base ' Display: calculate and display the number in the chosen base ' Repeat: ask if a new number and/or new base is wanted DECLARE SUB AskFor (NewBase AS INTEGER, Decimal AS DOUBLE, ExitFlag AS INTEGER) DECLARE SUB Display (NewBase AS INTEGER, Decimal AS DOUBLE) DECLARE SUB Repeat (ExitFlag AS INTEGER) DECLARE SUB Clearlines (Lower AS INTEGER, Upper AS INTEGER) DECLARE FUNCTION Convert$ (Digit AS INTEGER) ' Variables: ' NewBase: number base to which the decimal is to be converted ' Decimal: number to be converted to the new base ' ExitFlag: governs exit from loops for new base and new number DIM NewBase AS INTEGER, Decimal AS DOUBLE, ExitFlag AS INTEGER LET ExitFlag = 1 ' 0 = get new number, same base ' 1 = get new base, then new number ' 2 = quit program DO CALL AskFor(NewBase, Decimal, ExitFlag) CALL Display(NewBase, Decimal) CALL Repeat(ExitFlag) LOOP UNTIL ExitFlag = 2 END SUB AskFor (NewBase AS INTEGER, Decimal AS DOUBLE, ExitFlag AS INTEGER) '---------------------------------------------------------------------------- ' Ask the user to supply a new number and/or new base '---------------------------------------------------------------------------- ' Procedures: ' ClearLines: clear all text from part of the screen ' Parameters: ' NewBase: number base to which the decimal is to be converted ' Decimal: number to be converted to the new base ' ExitFlag: governs exit from loops for new base and new number ' Local Variables: ' RawBase: number base entered by the user (single precision) CLS COLOR 7, 1 ' White on blue CALL Clearlines(1, 3) PRINT TAB(25); "This program converts a number" PRINT TAB(29); "from decimal (base 10)" COLOR 11, 1 ' Bright cyan on blue PRINT TAB(23); "into a number base of your choice." COLOR 7, 0 ' Restore default white on black PRINT ' If ExitFlag = 1 then input and validate number base, ' else keep present base. IF ExitFlag = 1 THEN DO LOCATE 5, 1 PRINT SPC(70); " " LOCATE 5, 1 PRINT "Enter a number base between 2 and 62 :"; COLOR 12, 0 ' Input appears as bright red on black. INPUT " ", RawBase COLOR 7, 0 LOOP UNTIL RawBase > 1 AND RawBase < 63 AND INT(RawBase) = RawBase LET NewBase = CINT(RawBase) ELSE ' Remind the user of the existing base. LOCATE 5, 1 PRINT "The number base is"; COLOR 12, 0 ' Input appears as bright red on black. PRINT NewBase COLOR 7, 0 END IF ' Input and validate decimal number. DO LOCATE 7, 1 PRINT SPC(70); " " LOCATE 7, 1 PRINT "Enter a number between -30000 and +30000 :"; COLOR 12, 0 INPUT " ", Decimal COLOR 7, 0 LOOP UNTIL Decimal > -32768 AND Decimal < 32767 ' Provide information on the chosen base. CALL Clearlines(9, 17) LOCATE 9, 1 SELECT CASE NewBase CASE 2 TO 9 PRINT "Only digits 0 to"; (NewBase - 1); "are available in base"; PRINT NewBase; "." CASE 10 PRINT "This is the trivial case. The identity transformation "; PRINT "will occur." CASE 11 PRINT "Capital letter A will be used to represent the digit 10 "; PRINT "in base 11." CASE 12 TO 36 PRINT "Capital letters will be used to represent digits > 9," PRINT "from A = 10 to "; CHR$(54 + NewBase); PRINT " ="; (NewBase - 1); "in base"; NewBase; "." CASE 37 PRINT "Letters A to Z will be used to represent digits 10 to 35." PRINT "Letter a will be used to represent the digit 36 in base 37." CASE ELSE PRINT "Letters A to Z will be used to represent digits 10 to 35." PRINT "Letters a to "; CHR$(60 + NewBase); PRINT " will be used to represent digits 36 to"; (NewBase - 1); PRINT "in base"; NewBase; "." END SELECT END SUB SUB Clearlines (Lower AS INTEGER, Upper AS INTEGER) '---------------------------------------------------------------------------- ' Clear all text from part of the screen, from row (Lower) to row (Upper). '---------------------------------------------------------------------------- ' Procedures: ' ' Parameters: [as shown above] ' Local Variables: ' OldRow: remembers the row number where the cursor was. ' OldCol: remembers the column number where the cursor was. ' Row: loop counter = current row on screen DIM OldRow AS INTEGER, OldCol AS INTEGER, Row AS INTEGER LET OldRow = CSRLIN LET OldCol = POS(0) LOCATE Lower, 1 FOR Row = Lower TO Upper ' Blank only the chosen rows. PRINT SPC(78); " " NEXT Row LOCATE OldRow, OldCol ' Restore the cursor to its former location. END SUB DEFSTR C FUNCTION Convert (Digit AS INTEGER) '---------------------------------------------------------------------------- ' Convert a numeric digit into a string character. '---------------------------------------------------------------------------- ' No procedures or local variables. ' Parameters: ' Digit: the numeric digit to be converted SELECT CASE Digit CASE 0 TO 9 LET Convert = CHR$(48 + Digit) ' # can be represented by 0 - 9. CASE 10 TO 35 LET Convert = CHR$(55 + Digit) ' # can be represented by A - Z. CASE ELSE LET Convert = CHR$(61 + Digit) ' # can be represented by a - z. END SELECT END FUNCTION DEFSNG C SUB Display (NewBase AS INTEGER, Decimal AS DOUBLE) '---------------------------------------------------------------------------- ' Calculate and display the number in the chosen base '---------------------------------------------------------------------------- ' Procedures: ' Convert: convert a numeric digit to a string version DEFSTR C ' Parameters: ' NewBase: number base to which the decimal is to be converted ' Decimal: number to be converted to the new base ' Local Variables: ' Whole: whole number part of INT(|Decimal|); then remaining digits ' Sign: sign of the number ("-" or "+") ' Digit: string version of the current digit ' NewNum: string version of the number in the chosen base ' Place: location of current digit (to allow placement of spaces) ' MaxPower: governs maximum number of places due to limits of INTEGERs ' Frac: string version of the fractional part of the new number ' Format$: format string to print the user's number DIM Whole AS INTEGER, Place AS INTEGER, MaxPower AS INTEGER DIM Sign AS STRING, Digit AS STRING, NewNum AS STRING, Frac AS STRING LET Whole = INT(ABS(Decimal)) LOCATE 12, 1 IF Decimal = 0 THEN COLOR 12, 0 PRINT "Your number is ZERO IN ALL BASES!" COLOR 7, 0 ELSE ' ----------------- Convert the whole number part. ------------------- IF Decimal < 0 THEN LET Sign = "-" ELSE LET Sign = "+" ' Record SIGN of number. END IF ' Guard against rounding errors. IF 1 - ABS(Decimal) + Whole < .0001 THEN LET Whole = Whole + 1 LET Decimal = Whole * SGN(Decimal) END IF IF Whole < NewBase THEN LET NewNum = Convert(Whole) ' Here if number is a single digit. ELSE LET NewNum = Convert(Whole MOD NewBase) LET Whole = Whole \ NewBase LET Place = 1 DO WHILE Whole > 0 ' Avoid leading zeroes. LET Place = Place + 1 IF (Place - 1) MOD 3 = 0 THEN ' Space every third digit. LET NewNum = " " + NewNum END IF ' Insert new digit at left end of string. LET NewNum = Convert(Whole MOD NewBase) + NewNum LET Whole = Whole \ NewBase LOOP END IF ' ----------------- Convert any fractional part. ------------------ IF Decimal <> INT(Decimal) THEN LET MaxPower = INT(LOG(32767) / LOG(NewBase)) LET Whole = (ABS(Decimal) - INT(ABS(Decimal))) * NewBase ^ MaxPower LET Frac = Convert(Whole MOD NewBase) LET Whole = Whole \ NewBase FOR Place = (MaxPower - 1) TO 1 STEP -1 ' Keep leading zeroes. ' Construct from right to left. IF Place MOD 3 = 0 THEN LET Frac = " " + Frac ' Space every third digit. END IF LET Frac = Convert(Whole MOD NewBase) + Frac LET Whole = Whole \ NewBase NEXT Place LET NewNum = NewNum + "." + Frac END IF ' -------------------------------------------------------------------- LET NewNum = Sign + NewNum IF Decimal = INT(Decimal) THEN LET Format$ = " ##,###" ELSE LET Format$ = "##,###.#####" END IF PRINT TAB(10); COLOR 10, 1 ' Bright green on blue PRINT USING Format$; Decimal; PRINT " BASE 10 "; COLOR 15, 1 ' Bright white on blue PRINT "= "; COLOR 11, 1 ' Bright cyan on blue PRINT NewNum; " BASE"; NewBase COLOR 7, 0 END IF END SUB DEFSNG C SUB Repeat (ExitFlag AS INTEGER) '---------------------------------------------------------------------------- ' Ask the user if a new number and/or new base is wanted '---------------------------------------------------------------------------- ' Procedures: ' ' Parameters: ' ExitFlag: governs exit from loops for new base and new number ' Local Variables: ' Reply: upper case version of the key pressed by the user DIM Reply AS STRING LOCATE 15, 1 PRINT "Do you wish to convert another number in the same base (Y or N)? "; DO LET Reply = UCASE$(INKEY$) LOOP UNTIL Reply <> "" IF Reply = "N" THEN LET ExitFlag = 1 COLOR 12, 0: PRINT "No": COLOR 7, 0 ' Echo "No" in bright red. PRINT PRINT "Do you wish to convert a number to some other number base "; PRINT "(Y or N)? "; DO LET Reply = UCASE$(INKEY$) LOOP UNTIL Reply <> "" IF Reply = "N" THEN ' Quit option chosen. LET ExitFlag = 2 COLOR 12, 0: PRINT "No": COLOR 7, 0 LOCATE 23, 1 COLOR 10, 0 ' Bright green on black. PRINT "Thank you for using this program." COLOR 7, 0 END IF ELSE LET ExitFlag = 0 END IF END SUB