Jump to content

Number base conversion UDF


james3mg
 Share

Recommended Posts

Here is the culmination of a UDF script I've been thinking about for some time...it allows you to convert a number into another base. The output is a string, so it's ready for DISPLAY in your scripts, but also since it's a string, you can't expect AutoIt to know how to perform mathematical operations in the string's base.

There are three functions in the script (and no #includes), so it's nice and lightweight. _ToDec() allows you to convert a number in a supported base into a decimal number, _ToBase() allows you to convert a decimal number into a supported base, and _BaseToBase() uses both of the above to convert one supported base to another in one operation.

Supported bases are: all bases between 2 and 62 (inclusive). Decimal bases are supported and correctly rendered, though I've yet to hear of a useful application for them. Negative bases ARE NOT SUPPORTED. I love the theory behind them, but when I go to apply them, they confuse me quickly. Digits representing numbers greater than 9 are represented by case-sensitive english letters, capitals first.

The numbers being converted do not have to be integers, though numbers generated by decimal conversions may surprise you (or they may not, of course). For instance. 1 in binary is 1 in decimal. But 1.1 in binary is 1.5 in decimal, since .1 in binary is HALF of 1. Likewise, 1.1 in decimal is 1.0625 in hex (base 16), since .1 represents 1/16th of 1.

I hope you find this useful- the defaults I've selfishly set up for my most common tasks- I wrote this so I could have an easy way of actually viewing a real binary string (only 1s and 0s) rather than its hex representation. Hopefully I didn't miss any other, more obvious, application with better defaults :)

Let me know what you think! >_<

Edit: updated on 9/24/2008, due to an unintentional previous lack of support for converting negative numbers. Negative bases are still not supported.

You can use the below code to test the include file, but note the ConsoleWrite tends to truncate number strings:

$DecNum=_ToDec(11001.1,2)
If NOT @error Then
    ConsoleWrite($DecNum&@CRLF)
Else
    ConsoleWrite("Error: "&@error&@CRLF)
EndIf

$HexNum=_ToBase(25.5,2)
If NOT @error Then
    ConsoleWrite($HexNum&@CRLF)
Else
    ConsoleWrite("Error: "&@error&@CRLF)
EndIf

$ConvNum=_BasetoBase("F")
If NOT @error Then
    ConsoleWrite($ConvNum&@CRLF)
Else
    ConsoleWrite("Error: "&@error&@CRLF)
EndIf

BaseConv.au3 include file:

#include-once
Global $_BCaddlNums[63]=[0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

;   Function:   _ToDec()
;   Author:     james3mg
;   Summary:    Converts a number represented in a string from any positive base less than base 63 into decimal (base 10)
;               Numbers greater than 9 should be represented by English letters in ascending alphabetical order; capitols first.  CASE SENSITIVE!
;               See the $_BCaddlNums array at the top of this file for an ordered ranking of digits.
;               Negative bases are not supported; they confuse me too much in practice, though the theory is elegant.
;               Fractional bases (i.e. base 10.25) are correctly supported, but I can't imagine a useful application of them.
;   Arguments:
;               $_BCnum     The string to convert to decimal (base 10) (required)
;               $_BCbase    The base to convert $_BCnum from (optional: default is 16)
;   Return value:
;               Success:    A string representing the number expressed in the base requested
;               Failure:    Returns a blank string ("") and sets @error as following:
;                           @error=1    number string contains non-alphanumeric digits
;                           @error=2    invalid base number provided
;                           @error=3    a digit provided was not in the base provided (for instance a 2 occured in an allegedly binary string)

Func _ToDec($_BCnum,$_BCbase=16);converts the string from any positive base less than 63 into decimal (base 10)
    If $_BCbase=-1 Or $_BCbase=Default Then $_BCbase=16
    If NOT IsNumber($_BCbase) OR $_BCbase > 62 OR $_BCbase < 1 Then Return SetError(2)
    Local $_BCsign=""
    If StringLeft($_BCnum,1)="-" Then
        $_BCsign="-"
        $_BCnum=StringTrimLeft($_BCnum,1)
    EndIf
    Local $_SplitNum=StringSplit(String($_BCnum),"."),$_SplitNumInt=StringSplit($_SplitNum[1],""),$_i,$_n,$_BCreturnVal=""
    If NOT StringIsAlNum($_SplitNum[1]) Then Return SetError(1);number contains non-alphanumeric digits (to the left of the decimal)
    If $_SplitNum[0] <> 1 Then
        If $_SplitNum[0] <> 2 Then Return SetError(1);number contains non-alphanumeric digits (in this particular case, too many decimal points)
        If NOT StringIsAlNum($_SplitNum[2]) Then Return SetError(1);number contains non-alphanumeric digits (to the right of the decimal)
        Local $_SplitNumDec=StringSplit($_SplitNum[2],"")
    EndIf
;from here, we can guarentee the number passed the function could be a number in some base
    For $_i=1 To $_SplitNumInt[0]
        For $_n=10 To $_BCbase-1
            If $_SplitNumInt[$_i]==$_BCaddlNums[$_n] Then
                $_SplitNumInt[$_i]=$_n
                ExitLoop
            EndIf
        Next
        If NOT StringIsInt($_SplitNumInt[$_i]) OR $_SplitNumInt[$_i] > $_BCbase Then Return SetError(3);digit out of base range (for instance, 3 included in string given as binary)
    Next
    If $_SplitNum[0]=2 Then;if there was a decimal point
        For $_i=1 To $_SplitNumDec[0]
            For $_n=10 To $_BCbase-1
                If $_SplitNumDec[$_i]==$_BCaddlNums[$_n] Then
                    $_SplitNumDec[$_i]=$_n
                    ExitLoop
                EndIf
            Next
            If NOT StringIsInt($_SplitNumDec[$_i]) OR $_SplitNumDec[$_i] > $_BCbase Then Return SetError(3);digit out of base range
        Next
    EndIf
    
    For $_i=1 To $_SplitNumInt[0]
        $_BCreturnVal+=$_BCbase^($_i-1)*$_SplitNumInt[$_SplitNumInt[0]-($_i-1)]
    Next
    If $_SplitNum[0]=2 Then;if there was a decimal point
        For $_i=1 To $_SplitNumDec[0]
            $_BCreturnVal+=$_BCbase^(0-$_i)*$_SplitNumDec[$_i]
        Next
    EndIf
    Return SetError(0,0,$_BCsign&$_BCreturnVal)
EndFunc

;   Function:   _ToBase()
;   Author:     james3mg
;   Summary:    Converts a number represented in a string from any positive base less than base 63 into decimal (base 10)
;               Numbers greater than 9 are represented by English letters in ascending alphabetical order; capitols first.  CASE SENSITIVE!
;               See the $_BCaddlNums array at the top of this file for an ordered ranking of digits.
;               Decimals are supported, but remember that 1.1 in binary is represented by 1.5 in decimal, since .1 is HALF of a whole number in binary! (Doubling .1 in binary will give you 1.0)
;   !!!         NOTE: the output of this function is a STRING!  Do not expect AutoIt to know how to perform mathematical operations on the result in the correct base!
;               If you want to perform such operations, convert into decimal, run the operation, and convert back.
;               Negative bases are not supported; they confuse me too much in practice, though the theory is elegant.
;               Fractional bases (i.e. base 10.25) are correctly supported, but I can't imagine a useful application of them.
;   Arguments:
;               $_BCnum     The string to convert to the specified base (required)
;               $_BCbase    The base to convert $_BCnum into (optional: default is 16)
;               $_BClimit   The maximum number of decimal points returned (numbers to the RIGHT of the decimal point).  (optional: default is 12)  Note this has no effect on the number of digits to the left of the point (or if there is no point).
;   Return value:
;               Success:    A string representing the number expressed in the base requested
;               Failure:    Returns a blank string ("") and sets @error as following:
;                           @error=1    string is not a decimal (base 10) number
;                           @error=2    invalid base number provided

Func _ToBase($_BCnum,$_BCbase=16,$_BClimit=12);converts the decimal (base 10) string into any positive base less than 63
    If $_BCbase=-1 OR $_BCbase=default Then $_BCbase=16
    If $_BClimit=-1 OR $_BClimit=default Then $_BCbase=12
    If NOT IsNumber($_BCbase) OR $_BCbase > 62 OR $_BCbase < 1 Then Return SetError(2)
    Local $_BCsign=""
    If StringLeft($_BCnum,1)="-" Then
        $_BCsign="-"
        $_BCnum=StringTrimLeft($_BCnum,1)
    EndIf
    Local $_SplitNum=StringSplit(String($_BCnum),"."),$_i,$_BCreturnVal=""
    If Not StringIsDigit($_SplitNum[1]) Then Return SetError(1);not a decimal number
    If $_SplitNum[0] <> 1 Then
        If $_SplitNum[0] <> 2 Then Return SetError(1);not a decimal number (too many decimal points)
        If Not StringIsDigit($_SplitNum[2]) Then Return SetError(1);not a decimal number right of the decimal point
    EndIf
;now we can assume the number is valid
    Local $_MaxExp=Floor(Log($_BCnum)/Log($_BCbase));find out the digit length in destination base (actual digit length is 1 greater than this number, since 1 has a length of 1 and is 10^0)
    For $_i=$_MaxExp To 0 Step -1;loop through each digit to find the highest multiplier without going over
        $_BCreturnVal&=$_BCaddlNums[Floor($_BCnum/($_BCbase^$_i))]
        $_BCnum-=Floor($_BCnum/($_BCbase^$_i))*$_BCbase^$_i
    Next
    If $_SplitNum[0]=1 Then Return SetError(0,0,$_BCsign&$_BCreturnVal)
;if you get here, there's still decimal points to tally
    $_BCreturnVal&="."
    For $_i=-1 To $_BClimit*-1 Step -1
        $_BCreturnVal&=$_BCaddlNums[Floor($_BCnum/($_BCbase^$_i))]
        $_BCnum-=Floor($_BCnum/($_BCbase^$_i))*$_BCbase^$_i
        If $_BCnum=0 Then ExitLoop;don't add trailing zeros if an exact conversion is found
    Next
    Return SetError(0,0,$_BCsign&$_BCreturnVal)
EndFunc

;   Function:   _BaseToBase()
;   Author:     james3mg
;   Summary:    Converts a number represented in a string from any positive base less than base 63 into decimal (base 10)
;               Numbers greater than 9 are represented by English letters in ascending alphabetical order; capitols first.  CASE SENSITIVE!
;               See the $_BCaddlNums array at the top of this file for an ordered ranking of digits.
;               Decimals are supported, but remember that 1.1 in binary is represented by 1.5 in decimal, since .1 is HALF of a whole number in binary!
;   !!!         NOTE: the output of this function is a STRING!  Do not expect AutoIt to know how to perform mathematical operations on the result in the correct base!
;               If you want to perform such operations, convert into decimal, run the operation, and convert back.
;               Negative bases are not supported; they confuse me too much in practice, though the theory is elegant.
;               Fractional bases (i.e. base 10.25) are correctly supported, but I can't imagine a useful application of them.
;   Arguments:
;               $_BCnum         The string to convert to the specified base (required)
;               $_BCbaseOrig    The base to convert $_BCnum from (optional: default is 16)
;               $_BCbaseFinal   The base to convert $_BCnum into (optional: default is 2)
;               $_BClimit       The maximum number of decimal points returned (numbers to the RIGHT of the decimal point).  (optional: default is 12)  Note this has no effect on the number of digits to the left of the point (or if there is no point).
;   Return value:
;               Success:        A string representing the number expressed in the base requested
;               Failure:        Returns a blank string ("") and sets @error as following:
;                               @error=1    number string contains non-alphanumeric digits
;                               @error=2    invalid input base number provided
;                               @error=3    a digit provided was not in the base provided (for instance a 2 occured in an allegedly binary string)
;                               @error=4    unknown error (this should never happen- it means that _ToDec misfired somehow
;                               @error=5    invalid output base number provided

Func _BaseToBase($_BCnum,$_BCbaseOrig=16,$_BCbaseFinal=2,$_BClimit=12);errors 1-3 match errors 1-3 in _ToDec(); errors 4-5 match errors 1-2 in _ToBase()
    Local $_BCconv=_ToDec($_BCnum,$_BCbaseOrig)
    If @error Then Return SetError(@error)
    $_BCconv=_ToBase($_BCconv,$_BCbaseFinal,$_BClimit)
    If @error Then Return SetError(@error+3)
    Return SetError(0,0,$_BCconv)
EndFunc
Edited by james3mg
"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

Thanks! >_<

See the first post for an updated version; previously I'd forgotten to include support for converting negative numbers! :)

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...