Jump to content

Decimal to Binary number converter


LimeSeed
 Share

Recommended Posts

Here it is, you just type _binary($numberthatyouwanttoconverttobinary)

;binary app
#include <String.au3>

_binary(109)

Func _binary($num) ;converts a number to binary!
    dim $string = ""
    Do
        $num = $num/2
        if(floor($num) = $num) then
            $string = $string & "0"
        Else
            $string = $string & "1"
            $num -= .5
        EndIf
    Until ($num = 0)
    $string = _stringreverse($string)
    msgbox(0, "Binary", $string)
EndFunc
global $warming = true
Link to comment
Share on other sites

Alternatively..

Func _Convert_To_Binary($iNumber)
    Local $sBinString=""
    While $iNumber
        If BitAND($iNumber,1) Then 
            $sBinString='1'&$sBinString
        Else
            $sBinString='0'&$sBinString
        EndIf
        $iNumber=BitShift($iNumber,1)
    WEnd
    Return $sBinString
EndFunc
Link to comment
Share on other sites

Alternatively..

Func _Convert_To_Binary($iNumber)
    Local $sBinString=""
    While $iNumber
        If BitAND($iNumber,1) Then 
            $sBinString='1'&$sBinString
        Else
            $sBinString='0'&$sBinString
        EndIf
        $iNumber=BitShift($iNumber,1)
    WEnd
    Return $sBinString
EndFunc
yea that works too :)
global $warming = true
Link to comment
Share on other sites

Nice implementation. It is a trick though, specifically for converting decimals to binary numbers. A computer might be better off using a different algorithm.

That reminds me of an old post where we used real mathematics to convert decimals to binary. http://www.autoitscript.com/forum/index.php?showtopic=47144 That was crazy.

Link to comment
Share on other sites

Sweet. Even better! I don't think it can get better than that. Though hmm, we don't account for the # 0. Would have to put a test for that then. (If Not $iNumber Then Return "0")

Link to comment
Share on other sites

Sweet. Even better! I don't think it can get better than that. Though hmm, we don't account for the # 0. Would have to put a test for that then. (If Not $iNumber Then Return "0")

Oops, good point. Try this
Func _Convert_To_Binary($iNumber)
    Local $sBinString = ""
    Do
        $sBinString = BitAND($iNumber, 1) & $sBinString
        $iNumber = BitShift($iNumber, 1)
    Until $iNumber <= 0
    If $iNumber < 0 Then SetError(1, 0, 0)
    Return $sBinString
EndFunc   ;==>_Convert_To_Binary
Edit: The largest number this func handles is 2^31 -1 Edited by picaxe
Link to comment
Share on other sites

@ ptrex, neat UDF! Although it looks like the Binary conversion here is quicker. And neither does negative #'s properly.

@ picaxe, your code made me wonder why you're checking for less than 0, but then I did a quick test and was like WTH?? The first BitShift should have changed the number into a positive #, but it kept going as thought it were negative.

Then I read the Help on the different Bit ops and conversions, saw that it's all based on 32-bit signed numbers. I don't know whether AutoIt stores its #'s as 64-bit or not, but that would explain why the function would be caught in an endless loop. Normal machine bit-shift on a 32-bit # would make it positive on the first shift (since the uppermost bit contains the 'sign' flag), but the loop we had keeps working on a negative #.

Anyway, after a little tinkering and calculating, I've come up with a function that operates on any signed 32-bit number and returns the correct bit pattern.

The range for signed 32-bit values is -2147483648 to 2147483647. Note that the sign bit HAS to be part of the output, so a full 32-character string is required to display a negative 32-bit bit pattern properly.

Whew, and here I thought we had it pinned down. Anyway, after all that, here's the resultant function!

*EDIT: Added header for a 'nicer' look

; =================================================================================================
; Func _NumberToBinary($iNumber)
;
; Converts a 32-bit signed # to a binary bit string. (Limitation due to AutoIT functionality)
;   NOTE: range for 32-bit signed values is -2147483648 to 2147483647!
;       Anything outside the range will return an empty string!
;
; $iNumber = # to convert, obviously
;
; Returns:
;   Success: Binary bit string
;   Failure: "" and @error set
;
; Author: Ascend4nt, with help from picaxe (Changing 'If BitAND/Else' to just one line)
;   See it @ http://www.autoitscript.com/forum/index.php?showtopic=90056
; =================================================================================================

Func _NumberToBinary($iNumber)
    Local $sBinString = ""
    ; Maximum 32-bit # range is -2147483648 to 2147483647
    If $iNumber<-2147483648 Or $iNumber>2147483647 Then Return SetError(1,0,"")

    ; Convert to a 32-bit unsigned integer. We can't work on signed #'s
    $iUnsignedNumber=BitAND($iNumber,0x7FFFFFFF)
    
    ; Cycle through each bit, shifting to the right until 0
    Do
        $sBinString = BitAND($iUnsignedNumber, 1) & $sBinString
        $iUnsignedNumber = BitShift($iUnsignedNumber, 1)
    Until Not $iUnsignedNumber
    
    ; Was it a negative #? Put the sign bit on top, and pad the bits that aren't set
    If $iNumber<0 Then Return '1' & StringRight("000000000000000000000000000000" & $sBinString,31)
    
    Return $sBinString
EndFunc   ;==>_NumberToBinary
Edited by ascendant
Link to comment
Share on other sites

Another alteration that can be done is to match the padded 32-char string for both. Change the last 2 lines of the function into 1 line:

; Instead PAD BOTH of them and use the number test to decide the top bit
Return ($iNumber<0) & StringRight("000000000000000000000000000000" & $sBinString,31)

And sure, you can use the code - just credit the peeps responsible :)

Link to comment
Share on other sites

Another alteration that can be done is to match the padded 32-char string for both. Change the last 2 lines of the function into 1 line:

; Instead PAD BOTH of them and use the number test to decide the top bit
Return ($iNumber<0) & StringRight("000000000000000000000000000000" & $sBinString,31)

And sure, you can use the code - just credit the peeps responsible :)

I don't recommend doing that.

($iNumber<0) returns a boolean value. The boolean to string or number conversion is not guaranteed by AutoIt and it may be subject to change at any time. So if you want to write working code and keep it working in the future, don't concatenate boolean values.

Link to comment
Share on other sites

Would surrounding it in, say BitAND($iNumber<0,1) be better for ya?

I've never seen a True boolean result being other than 1 or -1, and to differ from that would be a little odd, no?

Edited by ascendant
Link to comment
Share on other sites

Would surrounding it in, say BitAND($iNumber<0,1) be better for ya?

I've never seen a True boolean result being other than 1 or -1, and to differ from that would be a little odd, no?

No, your original implementation is arguably better. Anything that relies on boolean to number conversion, without explicitly converting it, is wrong.

We've had this discussion some time back in Developer Chat, but I don't really recall where it is nor can I find it.

Link to comment
Share on other sites

No, your original implementation is arguably better. Anything that relies on boolean to number conversion, without explicitly converting it, is wrong.

We've had this discussion some time back in Developer Chat, but I don't really recall where it is nor can I find it.

Okay, sorry - with an explicit conversion: BitAnd(Number($iNumber<0,1),1). I just can think of too many cases where defaulting boolean-to-number conversion behavior would make sense for a language, that to remove it seems like it would break scripts. One case I can think of is passing a 'True' value in a DLLCall that I've seen done in a few code examples. Well, whatever the case, its a language that consistently breaks scripts with each new release, so I guess we'll find out what happens in the future :)

To avoid the boolean conversion and keep the functionality, you can do this instead:

$sBinString=StringRight("000000000000000000000000000000" & $sBinString,31)
If $iNumber<0 Then Return '1' & $sBinString
Return '0' & $sBinString
Link to comment
Share on other sites

@juozas, nice script, small and slick. And a good workaround for unsigned 32 bit numbers :)

And that's interesting about _Iif() - I didn't even know it existed

Link to comment
Share on other sites

..

Edited by Ascend4nt
Link to comment
Share on other sites

Dang, and here we all thought this topic was done and over with, right? Haha, no - it has risen from the dead! I give now to you the final version of this function (at least as far as 32-bits go - converting 64-bit numbers is for another thread :)

What did I add? The possibility to do unsigned numbers. I slapped myself in the head when the idea came to me. DUH - any number >2147483647 will have the topmost bit set (just as if it were a negative #). So all that was needed was a few small changes, and wa-la, I give you this full-range 32-bit converter. (You can change the Return based on your preference for consistent or situation-specific padding).

-Ascend4nt

; ==============================================================================================
; Func _NumberToBinary($iNumber)
;
; Converts a 32-bit signed or unsigned # to a binary bit string. (32-bit is AutoIT limit)
;   NOTE: range for 32-bit values is -2147483648 to 4294967295
;       Anything outside the range will return an empty string!
;
; $iNumber = # to convert, obviously
;
; Returns:
;   Success: Binary bit string
;   Failure: "" and @error set
;
; Author: Ascend4nt, with help from picaxe (Changing 'If BitAND/Else' to just one line)
;   See it @ http://www.autoitscript.com/forum/index.php?showtopic=90056
; ==============================================================================================

Func _NumberToBinary($iNumber)
    Local $iTopBit,$sBinString = ""
    ; Maximum 32-bit # range is -2147483648 to 4294967295   
    If $iNumber<-2147483648 Or $iNumber>4294967295 Then Return SetError(1,0,"")
    
    ; Any number <0 or >2147483647 will have the 32nd (top) bit set
    If $iNumber>2147483647 Or $iNumber<0 Then
        $iTopBit=1
    Else
        $iTopBit=0
    EndIf   

    ; Remove topbit, otherwise the function will enter an endless loop
    Local $iUnsignedNumber=BitAND($iNumber,0x7FFFFFFF)
    
    ; Cycle through each bit, shifting to the right until 0
    Do
        $sBinString = BitAND($iUnsignedNumber, 1) & $sBinString
        $iUnsignedNumber = BitShift($iUnsignedNumber, 1)
    Until Not $iUnsignedNumber

    ; PAD to 32-bits (or alternatively see below for #'s that don't need it)
    Return $iTopBit & StringRight("000000000000000000000000000000" & $sBinString,31)

; If you prefer not to pad numbers that don't need it (anything >0 and <2147483647):
#cs
    If $iTopBit Then Return $iTopBit & StringRight("000000000000000000000000000000" & $sBinString,31)
    Return $sBinString
#ce 
EndFunc   ;==>_NumberToBinary
nice job!
global $warming = true
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...