Jump to content

Reverse bits in a byte (opposite order)


Myicq
 Share

Go to solution Solved by UEZ,

Recommended Posts

This is probably totally obvious.. but my skills in bit operations could be improved a lot.

I have a string of bytes where I would like to reverse the order of the bits.

Principle:

; Input = 01000000  = 0x40
; Output = 00000010 = 0x02


consolewrite(reversebits(0x40))    ; returns 0x02
consolewrite(reversebits(0x20))    ; returns 0x04


func reversebits($inp)
   ; ...
   ; $out = ...__...
   return $out
endfunc

Can it be done with simple bitrotate ?

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

a lookuptable is probably fastest

http://graphics.stanford.edu/~seander/bithacks.html

Thanks for the link.

My skills in reading C code could be better.. are you thinking like "create an array with pre-calculated values and return $bitarray[input]" ? I guess there will be a maximum of 254 different values (0x00 and 0xFF should be obvious), so this is doable without too much trouble.

If I understood this idea wrong, let me know.

Edit: I would also think associative array  (Windows Object) or a simple sqLite in-Memory database would be possible. Question is which of the 3 would be the fastest ?

Edited by Myicq

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

  • Solution

Try this:

ConsoleWrite(Hex(ReverseBits(0x40), 8) & @LF)
ConsoleWrite(Hex(ReverseBits(0x20), 8) & @LF)

Func ReverseBits($n) ;coded by UEZ 2014
    Local $iBits
    Switch Ceiling(Log($n + 1) / Log(2))
        Case 0 To 8
            $iBits = 8
        Case 9 To 16
            $iBits = 16
        Case 17 To 32
            $iBits = 32
        Case Else
            $iBits = 64
    EndSwitch
    Local $iCount = 0, $i, $j = 0
    For $i = $iBits - 1 To 1 Step - 2
        $iCount += BitAND(BitShift($n, $i), 2 ^ $j)
        $j +=1
    Next
    For $i = 1 To $iBits - 1 Step 2
        $iCount += BitAND(BitShift($n, -$i), 2 ^ $j)
        $j +=1
    Next
    Return $iCount
EndFunc

Edit: code works only for unsigned integer numbers!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

The less sophisticated approach, operating on a single byte:

Func _ByteReverse($dByte)
    Local $iRet = 0
    For $i = 0 To 7
        $iRet += 2^(7 -$i)*(BitAND($dByte, 2^$i) = True)
    Next
    Return $iRet
EndFunc

Local $dTest = 0xA0
MsgBox(0, "_ByteReverse(" & $dTest & ")", _ByteReverse($dTest))
Edited by czardas
Link to comment
Share on other sites

Well, thank you very much to all contributors to this, especially you UEZ. I am astounded you have time to have a life outside helping people out here. Thumbs up!!

Did a small comparisons with different methods I had in mind.

Results, made on my not-extremely-fast Intel i3 machine, for 100.000 iterations:

  • In-Memory SQLite database using _SQLite_QuerySingleRow on integer fields : 45-50 seconds (this really surprised me...)
  • UEZ function as above: 3.9 seconds
  • Associative Array, using UDF from Ward (AssociativeArray.au3): 2.4 seconds
  • Normal linear array (256 positions) : 0.2 seconds

Although normal array is by far the fastest, I can recommend UEZ version for anything about 8 bits. Having 2^32 lines defining array values is not practical at all.

I have found a guy who did an informative Excel sheet on the topic. Adding to this, I have put the AutoIT codes to fill array values. Sheet is attached.

So once again thanks to UEZ. Great work! And to junkew for suggestion on fastest way.

reverse_bits.xls

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

Yes, you are right czardas. I forgot to mention it.

 

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

... another way

shorter but a few bits slower

ConsoleWrite(Hex(ReverseBits(0x40), 8) & @LF)
ConsoleWrite(Hex(ReverseBits(0x20), 8) & @LF)

Func ReverseBits($Byte)
    Local $out = 0
    For $i = 0 To 7
        $out = BitShift($out, -1)
        $out = BitOR($out, BitAND($Byte, 2 ^ $i) > 0)
    Next
    Return $out
EndFunc   ;==>ReverseBits

EDIT:

or only by manipulation of the bits

ConsoleWrite(Hex(ReverseBits(0x40), 8) & @LF)
ConsoleWrite(Hex(ReverseBits(0x20), 8) & @LF)

Func ReverseBits($Byte)
    Local $out = 0
    For $i = 0 To 7
        $out = BitOR(BitShift($out, -1), BitAND($Byte, 1))
        $Byte = BitShift($Byte, 1)
    Next
    Return $out
EndFunc   ;==>ReverseBits
Edited by PincoPanco

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

I modified my example to accept also negative numbers.

 

ConsoleWrite(Hex(ReverseBits(0x20)) & @LF)
ConsoleWrite(Hex(ReverseBits(12345678)) & @LF)
ConsoleWrite(Hex(ReverseBits(-8)) & @LF)
ConsoleWrite(Hex(ReverseBits(-12345678)) & @LF)

Func ReverseBits($n) ;coded by UEZ 2014 : from 11010010 (210) -> 01001011 (75)
    Local $iBits, $iLength = Ceiling(Log(Abs($n) + 1) / Log(2)), $m = $n
    $iBits = Ceiling($iLength / 4) * 4
    If $n < 0 Then $n = 2^$iBits - Abs($n)
    Local $iNumber = 0, $i, $j = 0
    For $i = $iBits - 1 To 1 Step - 2
        $iNumber += BitAND(BitShift($n, $i), 2 ^ $j)
        $j += 1
    Next
    For $i = 1 To $iBits - 1 Step 2
        $iNumber += BitAND(BitShift($n, -$i), 2 ^ $j)
        $j += 1
    Next
    If $m < 0 Then
        Local $iHex = Hex($iNumber, $iBits / 4), $i64 = "FFFFFFFFFFFFFFFFF"
        Return Dec($iHex & StringMid($i64, 1, 16 - StringLen($iHex)))
    EndIf
    Return $iNumber
EndFunc

It seems to work.

 

Br,

UEZ

Edit1: made the function shorter

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

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