Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Bit shifting in VB ? 1

Status
Not open for further replies.

fenris

Programmer
May 20, 1999
824
CA
Is it possible to shift bits like in c from VB? Is it also posible to use bitwise logical operators?

The reason that I am asking is that I have to store the various types of attributes that a file can have (ie read-only, archive, hidden etc.) in a database. I would prefer not to have to create a seperate field for each of the attributes.

Basically what I want to do is store a binary number like 1011 in the field representing which attributes are turned on and which are not.

Say I want to figure out if the third bit is on (third from the right ie from the least significant bit).

temp1 = 1011
temp2 = 100 'ie 1 shifted to the left 3 places
result = temp1 and temp2
result will yeild 0000 which indicates that the bit is off.

Would this be the best approach or is there a better way?

Thanks in advance




Troy Williams B.Eng.
fenris@hotmail.com

 
You can use logical functions (ie AND OR XOR) in VB on numbers. When you do, the funciton performs the logical operation on the bit level. For Example, 3 AND 5 = 1 since 0011 AND 0101 = 0001. So, using your example (in VB), you would use this . . .

temp1 = 11
temp2 = 4 'ie 1 shifted to the left 3 places
If (temp1 and temp2) = 0 then
'** Bit is turned off
else
'** Bit is turned on.
end if

Also, as in any shift operation, simply multiply or divide the number by the base number to shift. For example . . . in base 2, multiply the number by 2 to shift left and divide by 2 to shift right.
- Jeff Marler
(please note, that the page is under construction)
 
As much as I like VB, twiddlin' bits doesn't seem to be its strength. AND OR XOR IMP NOT work OK but shift or rotate?

There's always the rather unseemly using multiply & divide by powers of 2.

a = a * 8 'to shift to the left three
a = a \ 8 'to right shift

but these are replete with pitfalls
1) like overflow
2) what do you do to the high (or low) bits that are going to overflow.
3) mixing data types

But I'm curious as to what others think
 
To check for BITS falling off, youneed to check your division for remainders . . . and no, VB was not built for Bit level manipulation (aside from the basic bit mask), but if someone really wants to do bit manipulation in VB, there are ways. - Jeff Marler
(please note, that the page is under construction)
 
'This stuff I aquired somewhere, anyway I'm not the author
'maybe you guys would like to see it anyway
'There are two examples here

Option Explicit
Private m_lPower2(0 To 31) As LongPublic Function RShift(ByVal lThis As Long, ByVal _ lBits As Long) As Long
If (lBits <= 0) Then
RShift = lThis
ElseIf (lBits > 63) Then ' .. error ...
ElseIf (lBits > 31) Then
RShift = 0
Else
If (lThis And m_lPower2(31 - lBits)) = m_lPower2(31 - lBits) Then
Shift = (lThis And (m_lPower2(31 - lBits) - 1)) * m_lPower2(lBits) Or m_lPower2(31) Else
RShift = (lThis And (m_lPower2(31 - lBits) - 1)) * m_lPower2(lBits)
End If
End If
End Function

Public Function LShift(ByVal lThis As Long, ByVal lBits As Long) As Long
If (lBits <= 0) Then
LShift = lThis
ElseIf (lBits > 63) Then ' ... error ...
ElseIf (lBits > 31) Then
LShift = 0
Else
If (lThis And m_lPower2(31)) = m_lPower2(31) Then
LShift = (lThis And &H7FFFFFFF) \ m_lPower2(lBits) Or m_lPower2(31 - lBits)
Else
LShift = lThis \ m_lPower2(lBits)
End If
End If
End Function

Public Sub Init()
m_lPower2(0) = &H1&
m_lPower2(1) = &H2&
m_lPower2(2) = &H4&
m_lPower2(3) = &H8&
m_lPower2(4) = &H10&
m_lPower2(5) = &H20&
m_lPower2(6) = &H40&
m_lPower2(7) = &H80&
m_lPower2(8) = &H100&
m_lPower2(9) = &H200&
m_lPower2(10) = &H400&
m_lPower2(11) = &H800&
m_lPower2(12) = &H1000&
m_lPower2(13) = &H2000&
m_lPower2(14) = &H4000&
m_lPower2(15) = &H8000&
m_lPower2(16) = &H10000
m_lPower2(17) = &H20000
m_lPower2(18) = &H40000
m_lPower2(19) = &H80000
m_lPower2(20) = &H100000
m_lPower2(21) = &H200000
m_lPower2(22) = &H400000
m_lPower2(23) = &H800000
m_lPower2(24) = &H1000000
m_lPower2(25) = &H2000000
m_lPower2(26) = &H4000000
m_lPower2(27) = &H8000000
m_lPower2(28) = &H10000000
m_lPower2(29) = &H20000000
m_lPower2(30) = &H40000000
m_lPower2(31) = &H80000000
End Sub

--------------------------------------------------------------------------------


'In your Sub Main or Form_Load you MUST call Init:

Private Sub Form_Load()
Call Init
End Sub
'Where in C/C++ you did this: (I think)

'x = (x << 5);
'y = (y >> 8);

'You now do this:

'x = RShift(x, 5)
'y = LShift(y, 8)





#2
Option Explicit

Function RShift(ByVal lNum As Long, ByVal lBits As Long) As Long
If lBits <= 0 Then RShift = lNum
If (lBits <= 0) Or (lBits > 31) Then Exit Function

RShift = (lNum And (2 ^ (31 - lBits) - 1)) * _
IIf(lBits = 31, &H80000000, 2 ^ lBits) Or _
IIf((lNum And 2 ^ (31 - lBits)) = 2 ^ (31 - lBits), _
&H80000000, 0)
End Function

Function LShift(ByVal lNum As Long, ByVal lBits As Long) As Long
If lBits <= 0 Then LShift = lNum
If (lBits <= 0) Or (lBits > 31) Then Exit Function

If lNum < 0 Then
LShift = (lNum And &H7FFFFFFF) \ (2 ^ lBits) Or 2 ^ (31 - lBits)
Else
LShift = lNum \ (2 ^ lBits)
End If
End Function

Property Get LoWord(dwNum As Long) As Integer
LoWord = dwNum And &HFFFF
End Property

Property Let LoWord(dwNum As Long, ByVal wNewWord As Integer)
dwNum = dwNum And &HFFFF0000 Or wNewWord
End Property

Property Get HiWord(dwNum As Long) As Integer
HiWord = ((dwNum And IIf(dwNum < 0, &H7FFF0000, &HFFFF0000)) \ _
& H100 00) Or (-(dwNum < 0) * &H8000)
End Property

Property Let HiWord(dwNum As Long, ByVal wNewWord As Integer)
dwNum = dwNum And &HFFFF& Or IIf(wNewWord < 0, ((wNewWord And &H7FFF) _
* & H100 00) Or &H80000000, wNewWord * & H100 00)
End Property

Property Get LoByte(wNum As Integer) As Byte
LoByte = wNum And &HFF
End Property

Property Let LoByte(wNum As Integer, ByVal btNewByte As Byte)
wNum = wNum And &HFF00 Or btNewByte
End Property

Property Get HiByte(wNum As Integer) As Byte
HiByte = (wNum And &HFF00&) \ & H100
End Property

Property Let HiByte(wNum As Integer, ByVal btNewByte As Byte)
wNum = wNum And &HFF Or (btNewByte * & H100 &)
End Property
--------------------------------------------------------------------------------
Usages:

code:--------------------------------------------------------------------------------
Something = RShift(SomeValue, HowManyBits) ' Same with LShift

MyWord = HiWord(MyDWord) ' Get the HiWord (same way with LoWord)
HiWord(MyDWord) = MyWord ' Set the HiWord (same with LoWord)

MyByte = HiByte(MyWord) ' Get the HiByte (same with LoByte)
HiByte(MyWord) = MyByte ' Set the HiByte (same with LoByte)
--------------------------------------------------------------------------------



 
WOW!
OK . . .in all honesty, that was far more code than was needed for this operation. I would still stick to divide and multiple by 2 and then check for high end overflow on the mult. and remainders on the div. . . . assuming of course that I was staying in VB.
Actually, if I really wanted to get down and dirty on the bit level with VB, I would write a C++ DLL with exported API calls (NOT a COM interface . . . just simple APIs) that would implement all of the BIT level functionality that I wanted. I would then declare those function inside of VB and then do all the shifting I wanted! :)

- Jeff Marler
(please note, that the page is under construction)
 
Thank you for all the information. It is greatly appreciated. Hopefully I will get a chance to work on it tonight.


Thanks again.

Troy Williams B.Eng.
fenris@hotmail.com

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top