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.


# Conversion to/from negative base numbers                                    #
# Note - no checks for valid bases or digits bases -2 .. -63 are handled      #
#        A-Z represent the digits 11 .. 35, a-z represent the digits 36 .. 61 #
#        the digit 62 is represented by a space                               #
 
#                               1         2         3         4         5         6          #
#                               01234567890123456789012345678901234567890123456789012        #
[]CHAR base digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "[ AT 0 ];
 
# returns s decoded to an integer from the negative base b                   #
PRIO FROMNBASE = 9;
OP   FROMNBASE = ( STRING s, INT b )LONG INT:
     BEGIN
        LONG INT    result          := 0;
        LONG INT    base multiplier := 1;
        FOR d pos FROM UPB s BY -1 TO LWB s DO
            INT digit = IF   s[ d pos ] = " "
                        THEN 62
                        ELIF s[ d pos ] >= "a"
                        THEN ( ABS s[ d pos ] + 36 ) - ABS "a"
                        ELIF s[ d pos ] >= "A"
                        THEN ( ABS s[ d pos ] + 10 ) - ABS "A"
                        ELSE ABS s[ d pos ] - ABS "0"
                        FI;
            result          +:= base multiplier * digit;
            base multiplier *:= b
        OD;
        result
     END # FROMNBASE # ;
OP   FROMNBASE = ( CHAR c, INT b )LONG INT: STRING(c) FROMNBASE b;
 
# returns n encoded as a string in the negative base b #
PRIO TONBASE = 9;
OP   TONBASE = ( LONG INT n, INT b )STRING:
     BEGIN
        STRING   result := "";
        LONG INT v      := n;
        WHILE
            INT d := SHORTEN IF v < 0 THEN - ( ABS v MOD b ) ELSE v MOD b FI;
            v OVERAB b;
            IF d < 0
            THEN
                d -:= b;
                v +:= 1
            FI;
            base digits[ d ] +=: result;
            v /= 0
        DO SKIP OD;
        result
     END # TONBASE # ;
 
# tests the TONBASE and FROMNBASE operators #
PROC test n base = ( LONG INT number, INT base, STRING expected )VOID:
     BEGIN
        PROC expect = ( BOOL result )STRING: IF result THEN "" ELSE " INCORRECT" FI;
        STRING   encoded = number  TONBASE   base;
        LONG INT decoded = encoded FROMNBASE base;
        print( ( whole( number, 0 ), " encodes to: ", encoded ) );
        print( ( " base ", whole( base, 0 ), expect( encoded = expected ), newline ) );
        print( ( encoded, " decodes to: ", whole( decoded, 0 ) ) );
        print( ( " base ", whole( base, 0 ), expect( decoded = number   ), newline ) )
     END # test n base # ;
 
test n base(                    10,  -2,    "11110" );
test n base(                   146,  -3,    "21102" );
test n base(                    15, -10,      "195" );
# The defining document for ALGOL 68 spells the name "Algol 68" on the cover, though inside it is "ALGOL 68" #
# at the risk of "judging a language by it's cover", we use "Algol 68" as the name here...                   #
test n base( - LONG 36492107981104, -63, "Algol 68" )