Negative base numbers are an alternate way to encode numbers without the need for a minus sign. Various negative bases may be used including negadecimal (base -10), negabinary (-2) and negaternary (-3).[1][2]



Task

Encode the decimal number 10 as negabinary (expect 11110)
Encode the decimal number 146 as negaternary (expect 21102)
Encode the decimal number 15 as negadecimal (expect 195)
In each of the above cases, convert the encoded number back to decimal.


extra credit

 supply an integer, that when encoded to base   -62   (or something "higher"),   expresses the 
name of the language being used   (with correct capitalization).   If the computer language has 
non-alphanumeric characters,   try to encode them into the negatory numerals,   or use other 
characters instead.


MODULE NegativeBase;
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
 
CONST DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
TYPE String = ARRAY[0..63] OF CHAR;
 
PROCEDURE EncodeNegativeBase(n : LONGINT; base : LONGINT) : String;
    PROCEDURE Mod(a,b : LONGINT) : LONGINT;
    BEGIN
        RETURN a - (a / b) * b
    END Mod;
 
    PROCEDURE Swap(VAR a,b : CHAR);
    VAR t : CHAR;
    BEGIN
        t := a;
        a := b;
        b := t
    END Swap;
VAR
    ptr,idx : CARDINAL;
    rem : LONGINT;
    result : String;
BEGIN
    IF (base > -1) OR (base < -62) THEN
        RETURN result
    ELSIF n = 0 THEN
        result := "0"
    ELSE
        ptr := 0;
        WHILE n # 0 DO
            rem := Mod(n, base);
            n := n / base;
            IF rem < 0 THEN
                INC(n);
                rem := rem - base
            END;
            result[ptr] := DIGITS[rem];
            INC(ptr);
        END
    END;
    result[ptr] := 0C;
 
    idx := 0;
    DEC(ptr);
    WHILE idx < ptr DO
        Swap(result[idx], result[ptr]);
        INC(idx);
        DEC(ptr)
    END;
 
    RETURN result
END EncodeNegativeBase;
 
PROCEDURE DecodeNegativeBase(ns : String; base : LONGINT) : LONGINT;
VAR
    total,bb,i,j : LONGINT;
BEGIN
    IF (base < -62) OR (base > -1) THEN
        RETURN 0
    ELSIF (ns[0] = 0C) OR ((ns[0] = '0') AND (ns[1] = 0C)) THEN
        RETURN 0
    ELSE
        FOR i:=0 TO HIGH(ns) DO
            IF ns[i] = 0C THEN
                BREAK
            END
        END;
        DEC(i);
 
        total := 0;
        bb := 1;
        WHILE i >= 0 DO
            FOR j:=0 TO HIGH(DIGITS) DO
                IF ns[i] = DIGITS[j] THEN
                    total := total + j * bb;
                    bb := bb * base;
                    BREAK
                END
            END;
            DEC(i)
        END;
    END;
    RETURN total
END DecodeNegativeBase;
 
PROCEDURE Driver(n,b : LONGINT);
VAR
    ns,buf : String;
    p : LONGINT;
BEGIN
    ns := EncodeNegativeBase(n, b);
    FormatString("%12l encoded in base %3l = %12s\n", buf, n, b, ns);
    WriteString(buf);
 
    p := DecodeNegativeBase(ns, b);
    FormatString("%12s decoded in base %3l = %12l\n", buf, ns, b, p);
    WriteString(buf);
 
    WriteLn
END Driver;
 
BEGIN
    Driver(10, -2);
    Driver(146, -3);
    Driver(15, -10);
    Driver(-19425187910, -62);
 
    ReadChar
END NegativeBase.