A Binary-Octal-Decimal-Hexadecimal converter

Tony Marston - 1st June 2002

There may be occasions when you want to convert a decimal number into another format, such as binary, octal or hexadecimal. You may even want to convert a number in one of these other formats back into decimal. Uniface does not contain any standard functions to do this conversion, so you have to write your own routines.

This document describes the pair of routines which I wrote to perform this conversion. One converts from DECIMAL to BASEn, the other converts from BASEn to DECIMAL. For those of you who slept through your maths lessons I will translate:

The form which I use to test these routines looks like this:

tip32_01.gif

The field labeled Decimal (input) is for the decimal number. You can then press one of the DEC to BIN/OCT/HEX/B36 buttons in order to convert that number into the chosen format. If you then press one of the BIN/OCT/HEX/B36 to DEC buttons this will convert that value back into decimal and place the result in the Decimal (output) field.

To convert from decimal into one of the other formats I use the following code:

call DEC_TO_STRING(decimal_input, base, output_string)

where BASE is 2, 8, 16 or 36 (as explained above). The proc which is called looks like this:

entry DEC_TO_STRING     ; convert decimal number to baseN
params
   numeric pi_Decimal   : IN
   numeric pi_Base      : IN
   string  po_String    : OUT
endparams
variables
   string  lv_Charset
   numeric lv_Decimal
   numeric lv_Remainder
   string  lv_Char
endvariables

if (pi_Base < 2) | (pi_Base > 36) | (pi_Base = 10)
   message "BASE must be in the range 2-9 or 11-36"
   return(-1)
endif

; maximum character string is 36 characters
lv_Charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
; strip off excess characters (anything above pi_Base)
lv_Charset = lv_Charset[1,pi_Base] 

lv_Decimal = pi_Decimal                      ; move to work area
repeat
   ; get remainder after dividing by BASE
   lv_Remainder = (lv_Decimal % pi_Base)
   lv_Remainder = lv_Remainder + 1           ; starts from 1, not zero

   lv_Char      = lv_Charset[lv_Remainder:1] ; get CHAR from array
   po_String    = "%%lv_Char%%po_String"     ; add to output

   lv_Decimal   = lv_Decimal - (lv_Remainder -1)
   lv_Decimal   = lv_Decimal / pi_Base

until (lv_Decimal < 1)

return(0)

end DEC_TO_STRING

To convert from one of the other formats back into decimal I use the following code:

call STRING_TO_DEC(input_string, base, decimal_output)

where BASE must correspond to the format of INPUT_STRING. The proc which is called looks like this:

entry STRING_TO_DEC     ; convert baseN to decimal number
params
   string  pi_String    : IN
   numeric pi_Base      : IN
   numeric po_Decimal   : OUT
endparams
variables
   string  lv_Charset
   numeric lv_Base
   string  lv_String
   numeric lv_Remainder
   string  lv_Char
endvariables

if (pi_Base < 2) | (pi_Base > 36) | (pi_Base = 10)
   message "BASE must be in the range 2-9 or 11-36"
   return(-1)
endif

; maximum character string is 36 characters
lv_Charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
; strip off excess characters (anything above pi_Base)
lv_Charset = lv_Charset[1,pi_Base] 

lv_String  = pi_String          ; move to work area
repeat
   lv_Char   = lv_String[1:1]   ; extract leading character
   lv_String = lv_String[2]     ; drop leading character

   scan lv_Charset, lv_Char     ; get offset in Charset
   if ($result < 1)
      message "Illegal character (%%lv_Char) in INPUT string"
      return(-1)
   endif

   lv_Remainder = $result -1    ; starts from zero, not 1

   po_Decimal   = po_Decimal * pi_Base
   po_Decimal   = po_Decimal + lv_Remainder

until (lv_String = "")

return(0)

end STRING_TO_DEC

As you can see the code in each of my routines is not too complex. Feel free to copy them and add them to your own application library.

Click here to download my sample code.


Tony Marston
1st June 2002

mailto:tony@marston-home.demon.co.uk
mailto:TonyMarston@hotmail.com
http://www.tonymarston.net

counter