' Number base conversion: binary, octal, hex, decimal, custom digits
#COMPILE EXE
#DIM ALL

SUB DecToBin(BYVAL n AS LONG, BYREF result AS STRING)
    LOCAL r AS STRING
    IF n = 0 THEN
        result = "0"
        EXIT SUB
    END IF
    r = ""
    DO WHILE n > 0
        r = CHR$((n MOD 2) + 48) & r
        n = n / 2
    LOOP
    result = r
END SUB

SUB DecToOct(BYVAL n AS LONG, BYREF result AS STRING)
    LOCAL r AS STRING
    IF n = 0 THEN
        result = "0"
        EXIT SUB
    END IF
    r = ""
    DO WHILE n > 0
        r = CHR$((n MOD 8) + 48) & r
        n = n / 8
    LOOP
    result = r
END SUB

SUB DecToHex(BYVAL n AS LONG, BYREF result AS STRING)
    LOCAL digits AS STRING
    LOCAL r AS STRING
    digits = "0123456789ABCDEF"
    IF n = 0 THEN
        result = "0"
        EXIT SUB
    END IF
    r = ""
    DO WHILE n > 0
        r = MID$(digits, (n MOD 16) + 1, 1) & r
        n = n / 16
    LOOP
    result = r
END SUB

SUB DecToBase(BYVAL n AS LONG, BYVAL base AS LONG, BYREF result AS STRING)
    LOCAL digits AS STRING
    LOCAL r AS STRING
    IF base < 2 OR base > 36 THEN
        result = ""
        EXIT SUB
    END IF
    digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    IF n = 0 THEN
        result = "0"
        EXIT SUB
    END IF
    r = ""
    DO WHILE n > 0
        r = MID$(digits, (n MOD base) + 1, 1) & r
        n = n / base
    LOOP
    result = r
END SUB

FUNCTION BaseToDec(BYVAL s AS STRING, BYVAL base AS LONG) AS LONG
    LOCAL digits AS STRING
    LOCAL ch AS STRING
    LOCAL i AS LONG
    LOCAL c AS LONG
    LOCAL n AS LONG
    IF base < 2 OR base > 36 THEN
        FUNCTION = 0
        EXIT FUNCTION
    END IF
    digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    s = UCASE$(TRIM$(s))
    n = 0
    FOR i = 1 TO LEN(s)
        ch = MID$(s, i, 1)
        c = INSTR(digits, ch) - 1
        IF c < 0 OR c >= base THEN
            FUNCTION = 0
            EXIT FUNCTION
        END IF
        n = n * base + c
    NEXT i
    FUNCTION = n
END FUNCTION

FUNCTION PBMAIN() AS LONG
    LOCAL s AS STRING
    PRINT "=== Number Base Conversion ==="
    PRINT
    CALL DecToBin(255, s)
    PRINT "255 in binary: " & s
    CALL DecToOct(255, s)
    PRINT "255 in octal: " & s
    CALL DecToHex(255, s)
    PRINT "255 in hex: " & s
    CALL DecToHex(1024, s)
    PRINT "1024 in hex: " & s
    PRINT
    CALL DecToBase(42, 4, s)
    PRINT "42 in base-4: " & s
    PRINT "222(base-4) = " & FORMAT$(BaseToDec("222", 4))
    PRINT "FF(base-16) = " & FORMAT$(BaseToDec("FF", 16))
    PRINT "1100100(base-2) = " & FORMAT$(BaseToDec("1100100", 2))
    PRINT
    CALL DecToBase(100, 16, s)
    PRINT "100 in base-16: " & s
    CALL DecToBase(100, 8, s)
    PRINT "100 in base-8: " & s
    CALL DecToBase(100, 2, s)
    PRINT "100 in base-2: " & s
    PRINT
    PRINT "Number base tests complete."
    FUNCTION = 0
END FUNCTION
