|
|
|
| 14 February 2002 | CnvtBase2() |
| Author | W.M. Hinsch (New Mexico Mark) |
| Action | Within the numeric and string limits of KiXtart, converts any numeric base to any other numeric base. |
| Syntax | CnvtBase2 (Number, OldBase, NewBase [,NoHex] [,ForceSep]) |
| Parameters | |
| Remarks | I originally developed CnvtBase to convert any base 2-36 to any other base 2-36. However, in order to handle bases greater than 16, I used the alphabetic characters G-Z. The problems with that approach are: 1. Symbols beyond F for higher bases are not standardized. 2. I still had an upper limit of base 36. 3. There would have to be too much programming outside the function in order to handle these characters correctly. My solution is as follows: For bases 2-16, alphanumeric characters 0-9 and A-F may be supplied as a number (base 10 and below), string (bases 2-16) or array of digits with the least significant digit in element zero of the array. Other Notes: 1. The maximum *base 10* value of the supplied number cannot exceed KiXtart's 31-bit numeric limit. If this happens, the function will not necessarily have an error, but it will return incorrect results. 2. Error code 0 indicates function success, -1 for failure. |
| Returns | The number in the new base is returned as a string. If any digit in the returned string exceeds the maximum value for that base (9 for base 10 or 15 for base 16), separation characters will be included. For consistency, the function may be forced to include a separation character for any returned number. |
| Dependencies | None. |
| Examples |
$T1='190ACF'
$T2='-190'
'CnvtBase2(0,10,16) = ' + CnvtBase2(0,10,16) ?
'CnvtBase2(0,10,16,1) = ' + CnvtBase2(0,10,16,1) ?
'CnvtBase2(0,10,16,1,1) = ' + CnvtBase2(0,10,16,1,1) ?
'CnvtBase2("$T1",16,2) = ' + CnvtBase2($T1,16,2) ?
'CnvtBase2("$T1",16,2,1) = ' + CnvtBase2($T1,16,2,1) ?
'CnvtBase2("$T1",16,2,1,1) = ' + CnvtBase2($T1,16,2,1,1) ?
'CnvtBase2("110010000101011001111",16,2) = ' + CnvtBase2('110010000101011001111',2,16) ?
'CnvtBase2("110010000101011001111",16,2,1) = ' + CnvtBase2('110010000101011001111',2,16,1) ?
'CnvtBase2($T2,10,16,1) = ' + CnvtBase2($T2,10,16,1) ?
'CnvtBase2($T2,10,16) = ' + CnvtBase2($T2,10,16) ?
'CnvtBase2(2147483647,10,16) = ' + CnvtBase2(2147483647,10,16) ?
'CnvtBase2(2147483647,10,16,0,1) = ' + CnvtBase2(2147483647,10,16,0,1) ?
'CnvtBase2(2147483647,10,16,1,1) = ' + CnvtBase2(2147483647,10,16,1,1) ?
'CnvtBase2(2147483647,10,32) = ' + CnvtBase2(2147483647,10,32) ?
'Using CnvtBase2 to convert 4500 seconds to H:M:S' ?
'CnvtBase2(4500,10,60,1) = ' + CnvtBase2(4500,10,60,1) ?
'Converting 4:15:30 to seconds...' ?
'CnvtBase2("4:15:30",60,10) = ' + CnvtBase2('4:15:30',60,10) ?
; Console displays
;CnvtBase2(0,10,16) = 0
;CnvtBase2(0,10,16,1) = 0
;CnvtBase2(0,10,16,1,1) = 0
;CnvtBase2("190ACF",16,2) = 110010000101011001111
;CnvtBase2("190ACF",16,2,1) = 110010000101011001111
;CnvtBase2("190ACF",16,2,1,1) = 1:1:0:0:1:0:0:0:0:1:0:1:0:1:1:0:0:1:1:1:1
;CnvtBase2("110010000101011001111",16,2) = 190ACF
;CnvtBase2("110010000101011001111",16,2,1) = 1:9:0:10:12:15
;CnvtBase2(-190,10,16,1) = -11:14
;CnvtBase2(-190,10,16) = -BE
;CnvtBase2(2147483647,10,16) = 7FFFFFFF
;CnvtBase2(2147483647,10,16,0,1) = 7:F:F:F:F:F:F:F
;CnvtBase2(2147483647,10,16,1,1) = 7:15:15:15:15:15:15:15
;CnvtBase2(2147483647,10,32) = 1:31:31:31:31:31:31
;Using CnvtBase2 to convert 4500 seconds to H:M:S
;CnvtBase2(4500,10,60,1) = 1:15:0
;Converting 4:15:30 to seconds...
;CnvtBase2("4:15:30",60,10) = 15330
|
| Source |
FUNCTION CnvtBase2 ($vnum, $iob, $inb, OPTIONAL $bnohex, OPTIONAL $bforcesep)
; Generalized base conversion.
; SYNTAX: CnvtBase2(number or array,oldbase,newbase,[NoHex])
; Number=number (base 2-16 only) or array of digits w/MSD in
; element 0
; Oldbase=integer specifying the base of the supplied number
; Newbase=integer specifying the base to convert that number to
; NoHex=boolean true to use only characters 0-9 for return values
; ForceSep=boolean true to always separate digits with colons
; RETURNS: A string. If highest digit > 9 (or F if HEX allowed),
; or ForceSep is true, the digits will be delimited with colons
DIM $sdigits,$ssign,$stmp,$sdigit,$sbx,$ssep
DIM $ipos,$idigval,$ib10,$iplcnum,$i,$ilen ; $iB10=base 10 value
$iob=0+$iob
$inb=0+$inb
IF ($iob < 2) OR ($inb < 2)
EXIT -1
ENDIF
; Make vNum an array if necessary
IF VarType($vnum) < 8192
IF InStr($vnum,':') > 0
$vnum = Split($vnum,':')
ELSE
$stmp = '' + $vnum
$ilen = Len($stmp)
REDIM PRESERVE $vnum[$ilen-1]
FOR $i = 1 TO $ilen
$vnum[$i - 1] = Substr($stmp,$i,1)
NEXT
ENDIF
ENDIF
IF ($inb > 16) OR ($inb > 10 AND $bnohex) OR $bforcesep
$ssep = ':'
ELSE
$ssep = ''
ENDIF
$ipos=0 $idigval=0 $ib10=0 $i=0
$vremain='' $sbx='' $ssign='' $sdigit=''
$sdigits='0123456789ABCDEF'
$ilen=UBound($vnum)
; Preserve the sign, if supplied
IF ($vnum[0] = '-') OR ($vnum[0] = '+')
$ssign = $vnum[0]
FOR $i = 1 TO $ilen
$vnum[$i-1] = $vnum[$i]
NEXT
REDIM PRESERVE $vnum[$ilen - 1]
$ilen=UBound($vnum)
ENDIF
$iplcnum = 1
$ipos = 0
WHILE ($ipos <= $ilen) ; Convert to base 10
$sdigit = '' + $vnum[$ilen-$ipos]
IF (Len($sdigit) = 1)
$idigval = InStr($sdigits,$sdigit) - 1
ELSE
$idigval = 0 + $sdigit
ENDIF
IF $idigval > ($iob - 1)
EXIT -1
ENDIF
$ib10 = 0 + $ib10 + ($idigval * $iplcnum)
$iplcnum = $iplcnum * $iob
$ipos = $ipos + 1
LOOP
$ipos=0
WHILE ($ib10 > 0) ; Convert to new base
$vremain = $ib10 - (($ib10 / $inb) * $inb)
IF $bnohex OR $vremain > 15
$sbx = $ssep + $vremain + $sbx
ELSE
$sbx = $ssep + Substr($sdigits,$vremain+1,1) + $sbx
ENDIF
$ipos = $ipos + 1
$ib10 = $ib10 / $inb
LOOP
IF (Len($sbx) > 1) AND ($ssep = ':')
$sbx = Substr($sbx,2)
ENDIF
IF ($ssign <> '') ; Add the sign back in
$sbx = $ssign + $sbx
ENDIF
IF ($sbx = '')
$sbx='0'
ENDIF
$cnvtbase2 = $sbx
EXIT 0
ENDFUNCTION ; - CnvtBase2 -
|
|
|
|