 # Thread: >> and << functions for VB

1. ## >> 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```  Reply With Quote

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

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.  Reply With Quote

3. ## 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.)  Reply With Quote

4. ## 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.  Reply With Quote

5. ## 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```  Reply With Quote

6. ## 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```  Reply With Quote

7. ## 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```  Reply With Quote

8. ## 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.  Reply With Quote

9. ## Re: >> and << functions for VB

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).  Reply With Quote

10. ## Re: >> and << functions for VB

Recursion is looping in this case   Reply With Quote

11. ## Re: >> and << functions for VB Originally Posted by Merri Recursion is looping in this case Yes, but it will stop looping when Num=0 or Bits=0.   Reply With Quote

12. ## 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.  Reply With Quote

13. ## 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.  Reply With Quote

14. ## Re: >> and << functions for VB  Reply With Quote

#### Posting Permissions

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

Featured