A standard RETRO image only supports decimal base numbers. This shows a way to add support for multiple bases. I begin by creating a variable for the current base and words to set this to specific values quickly. ~~~ #10 'Base var :decimal #10 !Base ; :binary #2 !Base ; :octal #8 !Base ; :hex #16 !Base ; ~~~ Next, a string constant with the symbols for each digit. Note that I'm only going to support uppercase for hexadecimal. ~~~ '0123456789ABCDEF 'DIGITS s:const ~~~ So conversion to a numeric value is pretty easy. The basic idea here is: - set a variable to hold the numeric value to zero (as a stating point) - check to see if the first character is - for negative, set a modifier - for each character in the string: - convert to a numeric value (in this case, it's the index in the DIGITS string) - Multiply the last value of the number accumulator by the base - Add the converted value - Store the result in the number accumulator - Multiply the final number by the modifier ~~~ {{ 'Number var 'Mod var :convert (c-) &DIGITS swap s:index-of @Number @Base * + !Number ; :check-sign (s-s) dup fetch $- eq? [ #-1 !Mod n:inc ] [ #1 !Mod ] choose ; ---reveal--- :s:to-number (s-n) #0 !Number check-sign [ convert ] s:for-each @Number @Mod * ; }} ~~~ Going the other way, back to a string, follows a similar process. - Take a value - Repeat: - Divide by `Base` - Convert result to character and append to a buffer - If remainder is not zero, repeat - If number is negative, append the '-' symbol to the buffer - Reverse the buffer contents to return a string in the correct order ~~~ {{ 'String d:create #12 allot :check-sign (n-) n:negative? [ $- buffer:add ] if ; : n->digit (n-c) &DIGITS + fetch ; :convert (n-) [ @Base /mod swap n->digit buffer:add dup n:zero? ] until drop ; ---reveal--- :n:to-string (n-s) [ &String buffer:set dup n:abs convert check-sign ] buffer:preserve &String s:reverse ; }} ~~~