Jump to content

Dec To Binary


Lemures
 Share

Recommended Posts

Not the best way, but I don't want to steal Valik's thunder. (Plus, I'm too lazy to make sure my integer division routine works)

Func DecToBin($dec)
   Local $bin
   Local $hex = Hex($dec,8)
   Local $lookup = StringSplit("0001,0010,0011,0100,0101,0110,0111,1000,_
                                1001,1010,1011,1100,1101,1110,1111" , ',')
   $lookup[0] = '0000'

  ;convert hex to bin by using lookup table
   For $i = 1 to StringLen($hex)
      $tableIndex = Dec(StringMid($hex, $i, 1))
      $bin = $bin & $lookup[$tableIndex]
   Next
   
  ;strip leading zeros
   While StringLeft($bin,1) = "0"
      $bin = StringTrimLeft($bin,1)
   WEnd

   Return $bin
EndFunc

Edit: Fixed indention; I keep forgetting this forum dislikes tabs....

Edited by CyberSlug
Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
Link to comment
Share on other sites

I didn't test it heavily, but its ported from some code I wrote in C which works.

; DecToBin
; Parameters - $dec - IN - Decimal number to convert to binary
; Returns - The binary value on sucess, @error is set to 1 on error.
Func DecToBin($dec)
    If $dec < 1 Then   ; Sanity check
        SetError(1)
        Return ""
    EndIf
    
    Local $res = ""; Holds the result
    Local $cBase = 1

    While $cBase <= $dec
        $cbase = $cBase * 2
    WEnd
    
    While 1
        $val = Int($dec/$cBase)
        $dec = $dec - ($val * $cBase)
        
        If $val = 0 Then
            $res = $res & 0
        ElseIf $val = 1 Then
            $res = $res & 1
        Else
            SetError(1)
            Return ""
        EndIf
        If $cBase <= 1 Then ExitLoop
        $cBase = $cBase / 2
    WEnd
    Return StringTrimLeft($res, 1) ; Strip a leading 0 that isn't necessary
EndFunc
Link to comment
Share on other sites

:whistle: here's another way using BitAND magic:

Func DecToBin($dec)
   Local $bin, $i

   If $dec < 0 Then Return ""
   For $i = 0 To Log($dec)/Log(2);0 To Log-base-2 of $dec
      If BitAND($dec, 2^$i) >= 2^$i Then
         $bin = "1" & $bin
      Else
         $bin = "0" & $bin
      EndIf
   Next

   Return $bin
EndFunc

Note: You should add error checking; also, this function returns an empty string if $dec is zero.

Edited by CyberSlug
Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
Link to comment
Share on other sites

I would recommend CyberSlug's second post. The code I wrote was for a general base converter (Between 2 and 36), so it doesn't have any optimizations for some conversions. Since all I did was port that from C to AutoIt and hard-code it to be binary only, its probably not as fast as what he just posted.

Link to comment
Share on other sites

Hmm, there might be a bug in my second post... Try running this with my code:

For $i = 0 to 8
   MsgBox(0,$i, DecToBin($i))
Next

Once $i = 3, it just stays at three. Adding the line Local $i to my function fixes the problem.

Is this a scoping bug in AutoIt?

Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
Link to comment
Share on other sites

CyberSlug, yours go into an infinite loop... I was attempting to benchmark them and it never would finish. Here's some code (If you are on XP, you can see where it hangs with the TrayTip's)

Edit: Forgot to say, it hangs in your For loop. I see that you posted a fix, but it doesn't help it for me, it still loops over and over.

$t1 = TimerStart()
For $i = 0 To 100
    TrayTip("Loop1", $i, 5, 16)
    DecToBin(10000)
Next
$res1 = TimerStop($t1)
$t2 = TimerStart()
For $i = 0 To 100
    TrayTip("Loop2", $i, 5, 16)
    DecToBin2(10000)
Next
$res2 = TimerStop($t2)
MsgBox(4096, "", $res1 & @LF & $res2)


; DecToBin
; Parameters - $dec - IN - Decimal number to convert to binary
; Returns - The binary value on sucess, @error is set to 1 on error.
Func DecToBin($dec)
    If $dec < 1 Then  ; Sanity check
        SetError(1)
        Return ""
    EndIf
    
    Local $res = ""; Holds the result
    Local $cBase = 1

    While $cBase <= $dec
        $cbase = $cBase * 2
    WEnd
    
    While 1
        $val = Int($dec/$cBase)
        $dec = $dec - ($val * $cBase)
        
        If $val = 0 Then
            $res = $res & 0
        ElseIf $val = 1 Then
            $res = $res & 1
        Else
            SetError(1)
            Return ""
        EndIf
        If $cBase <= 1 Then ExitLoop
        $cBase = $cBase / 2
    WEnd
    Return StringTrimLeft($res, 1); Strip a leading 0 that isn't necessary
EndFunc

Func DecToBin2($dec)
  Local $bin

  If $dec < 0 Then Return ""
  For $i = 0 To Log($dec)/Log(2);0 To Log-base-2 of $dec
    TrayTip("Inside For", $i, 5, 16)
     If BitAND($dec, 2^$i) >= 2^$i Then
        $bin = "1" & $bin
     Else
        $bin = "0" & $bin
     EndIf
  Next

  Return $bin
EndFunc
Edited by Valik
Link to comment
Share on other sites

Everyone seems to have missed the easiest way...just using BitShift and BitAnd to pop off a bit at a time... :whistle:

The easiest way isn't always the most obvious, apparently. I didn't think of bit shifting at all, even after seeing CyberSlug use some Bit operators in his example. I need to remember this isn't C++ and these variables are typeless and I can do that sort of thing, too.
Link to comment
Share on other sites

I don't know about no bitAnd and all that crazy language you intelimegent people know but this should work. :whistle:

Func DecToBin($dec)
     $ans = ""
     While $dec >1
          $val = mod($dec,2)
          if $val <> 0 Then
               $val = 1
          EndIf
          $ans = $val & $ans
          $dec = int($dec / 2)
     Wend
     Return($dec & $ans)
EndFunc

I didn't see someone do this but should work. B)

red

Edited by redndahead
Link to comment
Share on other sites

I made yet another function that will convert nearly any number to any base between base 2 and base 62. It doesn't utilize bit shifting, isn't optimized in any way, and is a little absurd to be honest. ...But I thought that some people may find it a little interesting:

$NumberString = "27"
$StartBase = 10
$FinalBase = 16
MsgBox(0, "Result", $NumberString & " (base " & $StartBase & ") == " & nBaseConvert($NumberString, $StartBase, $FinalBase) & " (base " & $FinalBase & ")")
Exit

Func nBaseConvert($OrigNum, $OrigBase, $DestBase)
  If $OrigNum == "" Then Return SetError(1) 
  If Not IsInt($OrigBase) Then Return SetError(1)
  If Not IsInt($DestBase) Then Return SetError(1)
  If $OrigBase < 2 Or $OrigBase > 62 Or $DestBase < 2 Or $DestBase > 62 Then Return SetError(1)

  If $OrigBase > 36 Or $DestBase > 36 Then
    $CaseSense = 1
  Else
    $CaseSense = 0
  EndIf

  $Result = 0
  $BaseChr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  $OrigAry = StringSplit($OrigNum, "")

  For $i = 1 to (Ubound($OrigAry) - 1)
    $value = StringInStr($BaseChr, $OrigAry[$i], $CaseSense)
    If $value < 1 Or $value > $OrigBase Then Return SetError(1)
    $Result = ($Result * $OrigBase) + ($value - 1)
  Next

  $OutStr = ""
  If $Result < 0 Then Return SetError(1)
 
  While $Result
    $ModResult = Int(Mod($Result, $DestBase)) + 1
    $BaseLen = StringLen($BaseChr)
    If $ModResult <= $BaseLen Then
      $OutStr = StringMid($BaseChr, $ModResult, 1) & $OutStr
    Else
      Return SetError(1)
    EndIf

    $Result = Int($Result / $DestBase)
  Wend
Return $OutStr
EndFunc

Please note: Any character values [A-Z] in base 36 and below are parsed as Uppercase. Numbers in base 37 to base 62 will parse Upper and lower case characters differently. (Upper characters are first) If you have any questions on this, please let me know.

Link to comment
Share on other sites

:whistle: I even looked at BitShift

Func DecToBin($dec)
   Local $bin = ""
   If $dec < 1 Then Return "0"   

    While $dec > 0
      $bin = BitAND($dec, 1) & $bin
      $dec = BitShift($dec, 1)
   WEnd

   Return $bin
EndFunc
Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
Link to comment
Share on other sites

*doh* I wasn't thinking correctly. Made a couple of changes and removed 3 lines of code and added the ability to change from decimal to any type of value hopefully :whistle:

Func DecConvert($dec,$Div)
     $ans = ""
     While $dec > $Div - 1
          $val = mod($dec,$div)
          $ans = $val & $ans
          $dec = int($dec / $div)
     Wend
     Return($dec & $ans)
EndFunc

red

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...