Results 1 to 14 of 14

Thread: >> and << functions for VB

  1. #1

    Thread Starter
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    >> and << functions for VB

    VB does not have >> and << operators but we can create functions to simulate them.
    Without unsign data type other than Byte, so we can use only 31 right bits of Long (the largest Long number is 2^31-1).
    (Notation "&" below denotes a Long number)

    Edit: See New version in post#7

    Code:
    Function RShift(Num as Long, b as Byte) As Long 
    '--- Num >> b
       If Num > 0 then
          If b < 31 then
             '-- shift to the right with 0's patched to the left
             RShift = Num \ (2& ^ b)
          Else
             RShift = 0 '-- all bits are shifted away
          End if
       ElseIf Num = 0 then
          RShift = 0
       Else
          '-- can raise an error here
          MsgBox "Num must be >= 0"
       End If
    End Function
    Code:
    Function LShift(Num as Long, b as Byte) As Long
    '-- Num << b
       If Num > 0 then
          If b = 0 then
             LShift = Num '-- shift nothing
          ElseIf b < 31 then
             '-- Num mod 2&^(31-b) will shift the left-most bits away first to avoid overflow.
             '    * (2& ^ b) will shift the remaining bits to the left 
             '               with 0's patched to the right.
             LShift = (Num mod 2&^(31-b)) * (2& ^ b)
          Else 
             LShift = 0 '-- all bits are shifted away
          End if
       ElseIf Num = 0 then
          LShift = 0
       Else
          '-- can raise an error here
          MsgBox "Num must be >= 0"
       End If
    End Function
    Last edited by anhn; Jun 19th, 2010 at 09:02 PM.
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  2. #2
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    It is better to write bitshifting inline. Unfortunatenaly to have any performance you have to write a different line for different amount of bitshift:
    Code:
    Option Explicit
    
    Public Function Bit(ByVal Value As Long) As String
        Dim I As Long
        Bit = "00000000000000000000000000000000"
        If Value < 0 Then Value = Value And &H7FFFFFFF: Mid$(Bit, 1, 1) = "1"
        For I = 32 To 2 Step -1
            If Value And 1 Then Mid$(Bit, I, 1) = "1"
            Value = Value \ 2
        Next I
    End Function
    
    Private Sub Form_Load()
        Dim Shift As Long
        
        ' initial status
        Shift = &HFFFFFFFF
        Debug.Print "<< 0", Bit(Shift)
        
        ' left shift one bit
        Shift = (Shift And &H3FFFFFFF) * 2 Or -((Shift And &H40000000) > 0) * &H80000000
        Debug.Print "<< 1", Bit(Shift)
        
        ' left shift two bits
        Shift = (Shift And &H1FFFFFFF) * 4 Or -((Shift And &H20000000) > 0) * &H80000000
        Debug.Print "<< 2", Bit(Shift)
        
        ' left shift three bits
        Shift = (Shift And &HFFFFFFF) * 8 Or -((Shift And &H10000000) > 0) * &H80000000
        Debug.Print "<< 3", Bit(Shift)
        
        ' left shift four bits
        Shift = (Shift And &H7FFFFFF) * 16 Or -((Shift And &H8000000) > 0) * &H80000000
        Debug.Print "<< 4", Bit(Shift)
        
        ' left shift five bits
        Shift = (Shift And &H3FFFFFF) * 32 Or -((Shift And &H4000000) > 0) * &H80000000
        Debug.Print "<< 5", Bit(Shift)
        
        ' right shift one bit
        Shift = (Shift And &H7FFFFFFF) \ 2 Or -(Shift < 0) * &H40000000
        Debug.Print ">> 1", Bit(Shift)
        
        ' right shift two bits
        Shift = (Shift And &H7FFFFFFF) \ 4 Or -(Shift < 0) * &H20000000
        Debug.Print ">> 2", Bit(Shift)
        
        ' right shift three bits
        Shift = (Shift And &H7FFFFFFF) \ 8 Or -(Shift < 0) * &H10000000
        Debug.Print ">> 3", Bit(Shift)
        
        ' right shift four bits
        Shift = (Shift And &H7FFFFFFF) \ 16 Or -(Shift < 0) * &H8000000
        Debug.Print ">> 4", Bit(Shift)
        
        ' right shift five bits
        Shift = (Shift And &H7FFFFFFF) \ 32 Or -(Shift < 0) * &H4000000
        Debug.Print ">> 5", Bit(Shift)
    End Sub
    The Bit function is only for displaying the effect of the math. I only did the first five shifts for both left & right shift, because all the remaining ones are easy enough to write based on what has already been given.

    The bitshifting codes in this post are compatible with unsigned values.

  3. #3

    Thread Starter
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: >> and << functions for VB

    How can you remember all that to write inline for LShift and RShift with any bits from 0 to 32, and what hex numbers to use for 6 to 32 bits?

    I have seen a similar code somewhere on internet with a full Select Case from 0 to 32 bits (64 cases in total) for LShift() and RShift().
    Perhaps use bitwise operators inline is fast but too many cases and hex numbers to remember (cannot remember anyway.)
    Last edited by anhn; Jun 18th, 2010 at 06:06 AM.
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  4. #4
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    In most cases that I've needed unsigned bitshift I've also needed it in one or two spots in the entire code. Thus it doesn't really make it worth to write a function. Also, remembering the hex codes isn't required: you can see a logic in the five samples that I gave. Each next one is similar to what has been posted before, just the amount of zeros decrease (every fourth is similar, so 1 is similar to 5, 2 is similar to 6 etc.).

    You don't even need to take unsigned bit into account in every case: in some file formats the value is restricted already so that you'll never hit the highest bit. So the math would be simple Shift = Shift * 2 or Shift = Shift \ 2 for << 1 and >> 1. The sample codes I gave are valuable for those who need to have support for unsigned values.

    A lot of the cases you may be doing simple stuff such as combining two Integers to a Long – you don't even need to think it as a bitshift in those cases: Long = Low And &HFFFF& Or (High And &H7FFF&) * &H10000 Or -(High < 0) * &H80000000


    Personally I admit I really dislike any "do it via string" solution. It is an awful lot of performance waste, like using an excavator where a simple shovel would be fit. I wouldn't encourage anyone to use those methods for data processing. But if you need to display something then that is a different case – it just happens to be a very rare case, not really something you'd put up for end user unless the app is aimed towards knowleable people.

    I also think learning & knowing hex numbers is a good skill for any developer, be it VB or be it something else.

  5. #5

    Thread Starter
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: >> and << functions for VB

    Recursive method:
    Code:
    Function LShift(ByVal Num As Long, ByVal Bits As Byte) As Long
       If Num = 0 Or Bits = 0 Then LShift = Num Else _
       LShift = LShift((Num And &H3FFFFFFF) * 2 Or -((Num And &H40000000) > 0) * &H80000000, Bits - 1)
    End Function
    
    Function RShift(ByVal Num As Long, ByVal Bits As Byte) As Long
       If Num = 0 Or Bits = 0 Then RShift = Num Else _
       RShift = RShift((Num And &H7FFFFFFF) \ 2 Or -(Num < 0) * &H40000000, Bits - 1)
    End Function
    Code:
    Function Bin(ByVal Num As Long) As String
       Dim b As Long
       b = 32: Bin = String$(b, "0")
       If Num < 0 Then Mid$(Bin, 1, 1) = "1": Num = (Num And &H7FFFFFFF)
       Do Until (Num = 0) Or (b = 1)
          If (Num And 1) Then Mid$(Bin, b, 1) = "1"
          b = b - 1: Num = Num \ 2
       Loop
    End Function
    Code:
    Sub Test()
        Dim n0 As Long, n As Long, b As Byte
        
        n0 = Int(Rnd * 2 ^ 24) * (Int(Rnd * 2 ^ 8) - 2 ^ 7)
        b = 0
        Do
            n = LShift(n0, b)
            Debug.Print n0; "<<"; b, n, Hex(n), Bin(n)
            b = b + 1
        Loop Until n = 0
        Debug.Print String$(89, "-")
        b = 0
        Do
            n = RShift(n0, b)
            Debug.Print n0; ">>"; b, n, Hex(n), Bin(n)
            b = b + 1
        Loop Until n = 0
        Debug.Print String$(89, "=")
    End Sub
    Last edited by anhn; Jun 18th, 2010 at 09:08 AM.
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  6. #6
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    Recursion makes very little sense performance wise:
    Code:
    Function LShift(ByVal Num As Long, ByVal Bits As Byte) As Long
        If Bits < 32 Then
            For Bits = 1 To Bits: Num = (Num And &H3FFFFFFF) * 2 Or -((Num And &H40000000) > 0) * &H80000000: Next
            LShift = Num
        End If
    End Function
    
    Function RShift(ByVal Num As Long, ByVal Bits As Byte) As Long
        If Bits < 32 Then
            If Bits Then Num = (Num And &H7FFFFFFF) \ 2 Or -(Num < 0) * &H40000000
            For Bits = 2 To Bits: Num = Num \ 2: Next
            RShift = Num
        End If
    End Function

  7. #7

    Thread Starter
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: >> and << functions for VB

    The loop should be terminated when Num = 0, no need to keep shifting.
    Code:
    Function LShift(ByVal Num As Long, ByVal Bits As Byte) As Long
        If (Num = 0) Or (Bits >= 32) Then Exit Function
        Do Until (Bits = 0) Or (Num = 0)
            If (Num And &H40000000) = 0 Then Num = (Num And &H3FFFFFFF) * 2 _
                                        Else Num = (Num And &H3FFFFFFF) * 2 Or &H80000000
            Bits = Bits - 1
        Loop
        LShift = Num
    End Function
    
    Function RShift(ByVal Num As Long, ByVal Bits As Byte) As Long
        If (Num = 0) Or (Bits >= 32) Then Exit Function
        If Bits = 0 Then RShift = Num: Exit Function
        If Num < 0 Then Num = (Num And &H7FFFFFFF) \ 2 Or &H40000000: Bits = Bits - 1
        Do Until (Bits = 0) Or (Num = 0): Num = Num \ 2: Bits = Bits - 1: Loop
        RShift = Num
    End Function
    Code:
    Function Bin(ByVal Num As Long) As String
        Dim b As Byte, Bit(63) As Byte
        Bit(0) = 49 + ((Num And &H80000000) = 0)
        For b = 1 To 31:  Bit(2 * b) = 49 + ((Num And 2 ^ (31 - b)) = 0):  Next
        Bin = Bit
    End Function
    
    Function GetBit(ByVal Num As Long, ByVal Bit As Byte) As Byte
        '-- Bit number count right-to-left from 0 to 31
        If Bit < 31 Then
            If (Num And 2 ^ Bit) Then GetBit = 1
        ElseIf Bit = 31 Then
            If (Num And &H80000000) Then GetBit = 1
        End If
    End Function
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  8. #8
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    The math is so lightweight in compiled application that adding the extra check for value being zero mostly results only in a longer & possibly slower code. I don't find this much worth of benchmarking as inline code would be tremendously faster than any function call – you could do this calculation multiple times before it would become more time consuming than a single function call.

  9. #9

    Thread Starter
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: >> and << functions for VB

    Stick with your inline code method, that is your choice.
    I still like the recursive versions in this case because the code is so simple.
    No point to loop 31 times when doing RShift(1, 31) or LShift(&H80000000, 31).
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  10. #10
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    Recursion is looping in this case

  11. #11

    Thread Starter
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: >> and << functions for VB

    Quote Originally Posted by Merri View Post
    Recursion is looping in this case
    Yes, but it will stop looping when Num=0 or Bits=0.
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  12. #12
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    Then how about the second recursive call to RShift? At that point it is clearly pointless to check for the highest bit.

  13. #13
    Fanatic Member dmaruca's Avatar
    Join Date
    May 2006
    Location
    Jacksonville, FL
    Posts
    577

    Re: >> and << functions for VB

    Merri, hasn't this reached the point of "who cares" yet? Sure performance MAY be affected, but most cases in vb code it will never make a difference. I dare say that the performance that really counts is being able to write the code faster and meet deadlines at work. If you have to shift so many bits that it becomes a bottleneck, it can be dealt with then. Otherwise too much time spent.

  14. #14
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: >> and << functions for VB

    But we aren't talking about work deadlines here.
    Last edited by Merri; Jun 27th, 2010 at 10:32 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width