[RESOLVED] Boolean or Byte or Bit ?
I need to define some UDTs like:
Code:
Type Elem_Options
Option1 As Boolean
Option2 As Boolean
Option3 As Boolean
Option4 As Boolean
Option5 As Boolean
Option6 As Boolean
Option7 As Boolean
Option8 As Boolean
Option9 As Boolean
Option10 As Boolean
Option11 As Boolean
Option12 As Boolean
Option13 As Boolean
Option14 As Boolean
End Type
Private m_ElemOptions(1000000) As Elem_Options
Elem_Options needs to occupy 28 bytes. If I change Boolean to Byte, Elem_Options only need to occupy 14 bytes:
Code:
Type MyOptions
Option1 As Byte
Option2 As Byte
Option3 As Byte
Option4 As Byte
Option5 As Byte
Option6 As Byte
Option7 As Byte
Option8 As Byte
Option9 As Byte
Option10 As Byte
Option11 As Byte
Option12 As Byte
Option13 As Byte
Option14 As Byte
End Type
Private m_ElemOptions(1000000) As Elem_Options
I'd like to know the advantages and disadvantages of the above two methods. After changing Boolean to Byte, will it affect the performance of the software? Thanks !
Also, is it necessary to change Byte to Bit?
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
SearchingDataOnly
I need to define some UDTs like:
I'd like to know the advantages and disadvantages of the above two methods. After changing Boolean to Byte, will it affect the performance of the software? Thanks !
Also, is it necessary to change Byte to Bit?
Advantage: Less memory used
Disadvantage: Not intuitive for reading code nevermind implicit TypeCast/-Conversion might run havoc and hide Bugs
I wouldn't know of a BIT-DataType.....
The way i would do it:
If you need 14 Booleans (True/False), you would need 14 Bits, which rounds up to 16 Bits, which is 2 Bytes, which corresponds with 2-Byte Integer, and do it via masking
e.g.
The integer-value "3" is binary "0000 0000 0000 0011"
So, to check if Option2 is set you just do a
"If MyOptionInteger And 2 Then Debug.Print "Option2 is True"
Or for Option4
"If MyOptionInteger And 8 Then Debug.Print "Option4 is False"
So, where you take 14/28 Bytes, i take 2
Re: Boolean or Byte or Bit ?
If you really need it dimmed to a million, I'd tend to write some procedures for setting and checking bits. That'd reduce your memory needs by a factor of 8 over Bytes and a factor of 16 over Booleans.
Just as an FYI, Booleans are just a special case of Integers (which are two bytes), although the compiler and the runtime engine try to keep them as either 0 or -1, but not always.
Re: Boolean or Byte or Bit ?
Boolean, as mentioned by Elroy, would be 2 bytes per value. 14 values is 28b per, and if you're planning to have 1m of these it'll take up 28MB of memory.
If you chose Byte, it'd be 1 byte per value so that's 14MB.
If, as mentioned, you set up a function that took a value and returned the value of that point (or set the value) you would use about 1.75MB...a fraction of the above. I'm sure you can work out ways to do it with a byte array storing the relative values, it's not too difficult.
If memory is your only requirement (which you haven't specified) the byte array referencing function would definitely perform the best...surprisingly, there are ways in which you could take things even further by compressing the bit data (I had a tree method for compressing weighted bit streams of data that has very few 1s...complicated stuff :-))...it's adding more processing but reducing memory overheads.
If you're looking for speed over memory, I would think byte is best as it's only one byte (rather than two) and takes less time to access...worth testing if you were that worried about the potential speed issues.
Re: Boolean or Byte or Bit ?
Does it take less time to access? I don't know how VB6 accesses data, but I don't think there is any advantage to shifting one byte into a register. I'm not even sure it's truly possible, which is probably why a Boolean is taking two bytes when it technically only needs a single bit.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Shaggy Hiker
Does it take less time to access? I don't know how VB6 accesses data, but I don't think there is any advantage to shifting one byte into a register. I'm not even sure it's truly possible, which is probably why a Boolean is taking two bytes when it technically only needs a single bit.
That's actually a good point. I haven't tested, but it might actually take more time to test a Byte than to test a Boolean. If it's forced to use a 16-bit register (which I'd suspect it is), with a Byte, it's going to load the next byte so it'll need to zero it out (or maybe there are 8-bit tests). With a Boolean (two bytes), it can just load and test, no zeroing needed.
EDIT: Actually, it's been a while since I've messed with assembly, but I just looked at the Pentium instruction set, and there are 8-bit move instructions, so maybe a Byte would be a couple of ticks faster.
Re: Boolean or Byte or Bit ?
I suppose there is always RtlInitializeBitMap and friends. Using a typlib should shave a little overhead.
Quote:
Remarks
A driver can use a bitmap variable as an economical way to keep track of a set of reusable items. For example, file systems use a bitmap variable to track which clusters/sectors on a disk have already been allocated to hold file data. The system-supplied SCSI port driver uses a bitmap variable to track which queue tags have been assigned to SCSI request blocks (SRBs).
These work in normal user programs as well as drivers.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Zvoni
Advantage: Less memory used
Disadvantage: Not intuitive for reading code nevermind implicit TypeCast/-Conversion might run havoc and hide Bugs
I wouldn't know of a BIT-DataType.....
The way i would do it:
If you need 14 Booleans (True/False), you would need 14 Bits, which rounds up to 16 Bits, which is 2 Bytes, which corresponds with 2-Byte Integer, and do it via masking
e.g.
The integer-value "3" is binary "0000 0000 0000 0011"
So, to check if Option2 is set you just do a
"If MyOptionInteger And 2 Then Debug.Print "Option2 is True"
Or for Option4
"If MyOptionInteger And 8 Then Debug.Print "Option4 is False"
So, where you take 14/28 Bytes, i take 2
Quote:
Originally Posted by
Elroy
If you really need it dimmed to a million, I'd tend to write some procedures for setting and checking bits. That'd reduce your memory needs by a factor of 8 over Bytes and a factor of 16 over Booleans.
Just as an FYI, Booleans are just a special case of Integers (which are two bytes), although the compiler and the runtime engine try to keep them as either 0 or -1, but not always.
Quote:
Originally Posted by
SmUX2k
Boolean, as mentioned by Elroy, would be 2 bytes per value. 14 values is 28b per, and if you're planning to have 1m of these it'll take up 28MB of memory.
If you chose Byte, it'd be 1 byte per value so that's 14MB.
If, as mentioned, you set up a function that took a value and returned the value of that point (or set the value) you would use about 1.75MB...a fraction of the above. I'm sure you can work out ways to do it with a byte array storing the relative values, it's not too difficult.
If memory is your only requirement (which you haven't specified) the byte array referencing function would definitely perform the best...surprisingly, there are ways in which you could take things even further by compressing the bit data (I had a tree method for compressing weighted bit streams of data that has very few 1s...complicated stuff :-))...it's adding more processing but reducing memory overheads.
If you're looking for speed over memory, I would think byte is best as it's only one byte (rather than two) and takes less time to access...worth testing if you were that worried about the potential speed issues.
Yes, using Bit seems to be the better approach, although it requires more code to be written. I plan to use "Dim BitArray(1) As Byte" to hold 16 Bits. Thanks Zvoni, Elroy and SmUX2k.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Shaggy Hiker
Does it take less time to access? I don't know how VB6 accesses data, but I don't think there is any advantage to shifting one byte into a register. I'm not even sure it's truly possible, which is probably why a Boolean is taking two bytes when it technically only needs a single bit.
Quote:
Originally Posted by
Elroy
That's actually a good point. I haven't tested, but it might actually take more time to test a Byte than to test a Boolean. If it's forced to use a 16-bit register (which I'd suspect it is), with a Byte, it's going to load the next byte so it'll need to zero it out (or maybe there are 8-bit tests). With a Boolean (two bytes), it can just load and test, no zeroing needed.
EDIT: Actually, it's been a while since I've messed with assembly, but I just looked at the Pentium instruction set, and there are 8-bit move instructions, so maybe a Byte would be a couple of ticks faster.
Yes, I've heard a point before that using Long is faster than Integer, maybe because of the registers. This is also why I worry that Byte is slower than Boolean. Thank you, Shaggy Hiker and Elroy.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
dilettante
I suppose there is always
RtlInitializeBitMap and friends. Using a typlib should shave a little overhead.
These work in normal user programs as well as drivers.
This is a very attractive proposition. It would be better if there is a simple example to demonstrate how to use RtlInitializeBitMap to store multiple Bits. Thank you, dilettante.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
SearchingDataOnly
Yes, using Bit seems to be the better approach, although it requires more code to be written. I plan to use "Dim BitArray(1) As Byte" to hold 16 Bits. Thanks Zvoni, Elroy and SmUX2k.
If you want to use 2 bytes like that, the integer datatype has the value -32768 to 32767 (so a total of 65536) and uses only 2 bytes. It does require that you shift the value by 32768 into another variable before you do the bit checking so it may be extra processing, but it would mean that you could have one huge integer array that stored all the bits and can easily be referenced by number. Another option is a unicode string (which uses 2 bytes per character), but that's not going to be much different to integer and will also require extra processing.
If speed is of importance, you may have to stress-test different options to see which is fastest in your case...it's often something I don't worry too much about as the miniscule differences in speed don't usually affect my code (or at least it doesn't have enough of an effect to bother me). If memory is highest importance, the integer datatype is probably going to be best though not considerably better than the byte option.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
SmUX2k
If you want to use 2 bytes like that, the integer datatype has the value -32768 to 32767 (so a total of 65536) and uses only 2 bytes. It does require that you shift the value by 32768 into another variable before you do the bit checking so it may be extra processing, but it would mean that you could have one huge integer array that stored all the bits and can easily be referenced by number. Another option is a unicode string (which uses 2 bytes per character), but that's not going to be much different to integer and will also require extra processing.
If speed is of importance, you may have to stress-test different options to see which is fastest in your case...it's often something I don't worry too much about as the miniscule differences in speed don't usually affect my code (or at least it doesn't have enough of an effect to bother me). If memory is highest importance, the integer datatype is probably going to be best though not considerably better than the byte option.
The reason why I use "Dim BitArray(1) As Byte" is to be able to expand to BitArray(2) or BitArray(3) in the future. In fact, Long (4 bytes) saves 32 bits, which is enough to meet my future expansion needs. But I don't know how to do Bit operations on Long yet.
Re: Boolean or Byte or Bit ?
Code:
Option Explicit
Private m_Bits(31) As Long
Public Sub InitBits()
Dim i As Long, lBits As Long
lBits = 1
For i = 0 To 30
m_Bits(i) = lValue
If i < 30 Then lBits = lBits * 2
Next i
m_Bits(31) = -2147483648#
End Sub
Public Sub SetBit(lValue As Long, ByVal lIndex As Long)
' Sets indicated bit to one, or ON.
Dim indx As Long, ofst As Long
indx = lIndex \ 32
ofst = lIndex And 31&
lValue(indx) = lValue(indx) Or m_Bits(ofst) 'turn the bit ON
End Sub
Public Function GetBit(lValue As Long, ByVal lIndex As Long) As Long
' Returns zero if the indicated bit is off, NON-ZERO if on.
Dim indx As Long, ofst As Long
indx = lIndex \ 32
ofst = lIndex And 31& 'posn MOD 32
GetBit = lValue And m_Bits(ofst)
End Function
Public Function IsBitSet(lValue As Long, ByVal lIndex As Long) As Boolean
' Returns zero if the indicated bit is off, NON-ZERO if on.
Dim indx As Long, ofst As Long
indx = lIndex \ 32
ofst = lIndex And 31& 'posn MOD 32
IsBitSet = (lValue And m_Bits(ofst)) <> 0
End Function
Public Sub ClearBit(lValue As Long, ByVal posn As Long)
' Sets indicated bit to zero, or OFF.
Dim indx As Long, ofst As Long
indx = posn \ 32
ofst = posn And 31 ' BITS0thru4 ' posn MOD 32
lValue = lValue And (Not m_Bits(ofst)) 'turn the bit OFF
End Sub
Public Function CountBits(lValue As Long) As Long
Dim lValue As Long
If lValue Then
If lValue = -1 Then
CountBits = CountBits + 32
Else
If lValue And &H1 Then CountBits = CountBits + 1
If lValue And &H2 Then CountBits = CountBits + 1
If lValue And &H4 Then CountBits = CountBits + 1
If lValue And &H8 Then CountBits = CountBits + 1
If lValue And &H10& Then CountBits = CountBits + 1
If lValue And &H20& Then CountBits = CountBits + 1
If lValue And &H40& Then CountBits = CountBits + 1
If lValue And &H80& Then CountBits = CountBits + 1
If lValue And &H100& Then CountBits = CountBits + 1
If lValue And &H200& Then CountBits = CountBits + 1
If lValue And &H400& Then CountBits = CountBits + 1
If lValue And &H800& Then CountBits = CountBits + 1
If lValue And &H1000& Then CountBits = CountBits + 1
If lValue And &H2000& Then CountBits = CountBits + 1
If lValue And &H4000& Then CountBits = CountBits + 1
If lValue And &H8000& Then CountBits = CountBits + 1
If lValue And &H10000 Then CountBits = CountBits + 1
If lValue And &H20000 Then CountBits = CountBits + 1
If lValue And &H40000 Then CountBits = CountBits + 1
If lValue And &H80000 Then CountBits = CountBits + 1
If lValue And &H100000 Then CountBits = CountBits + 1
If lValue And &H200000 Then CountBits = CountBits + 1
If lValue And &H400000 Then CountBits = CountBits + 1
If lValue And &H800000 Then CountBits = CountBits + 1
If lValue And &H1000000 Then CountBits = CountBits + 1
If lValue And &H2000000 Then CountBits = CountBits + 1
If lValue And &H4000000 Then CountBits = CountBits + 1
If lValue And &H8000000 Then CountBits = CountBits + 1
If lValue And &H10000000 Then CountBits = CountBits + 1
If lValue And &H20000000 Then CountBits = CountBits + 1
If lValue And &H40000000 Then CountBits = CountBits + 1
If lValue And &H80000000 Then CountBits = CountBits + 1
End If
End If
End Function
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
SearchingDataOnly
The reason why I use "Dim BitArray(1) As Byte" is to be able to expand to BitArray(2) or BitArray(3) in the future. In fact, Long (4 bytes) saves 32 bits, which is enough to meet my future expansion needs. But I don't know how to do Bit operations on Long yet.
If you used 2 integer arrays (or a 2-dimensional array?) you would have that option, you just use the first array as the lower bits (1-16) and the second arrays as the higher bits (17-32). If you wanted to reduce the overheads you could use the byte datatype and expand it from 2 to 3 when you need the third level of 8 and 3 to 4 when you need that last level of 8.
Me, I would go with the byte option if I knew I had potential for needing expansion and wanted to minimise the overheads.
So if you needed 1m positions and wanted to support up to 32 bits, you would use Dim BitArray(3,1000000) As Byte if you chose to use multidimensional array). If you do a bitcheck on BitArray(0,1) it would give results for the first 8 bits of the first value, a bitcheck on BitArray(1,1) would give results for the next 8, etc.
All you need is a function that simplifies this by taking a value for the bit point you're after and the position in the array you want and does the calculations for where to look and returning the result, as in BitAt(1,100) (just an example name, it needs to be coded :-P) which would return the 1st bit value in the 100th number...I could probably write something in about 5 minutes that would do it, and just sits in a module waiting to be called. The usefulness of this is that if you needed (at design time) to raise the number of bits you could easily do it by adding to the bit portion of the variable.
Using a Long would seem overly processor intensive to me, as you would need to check 2^point and with Longs that becomes a huge number...keeping it to bytes (or integers) simplifies things in some ways
Re: Boolean or Byte or Bit ?
Very quick bit of code that seems to work for me, and much smaller than the one offered above:
Code:
Public BitArray(3, 1000000) As Byte
Public Function getbit(point As Single, loc As Double)
arrloc = 0: temppoint = point
Do While temppoint > 8 'Gets the position along the dimensions
temppoint = temppoint - 8: arrloc = arrloc + 1
Loop
getbit = BitArray(arrloc, loc) And 2 ^ (temppoint - 1)
End Function
Public Function setbit(point As Single, loc As Double, valu As Boolean)
arrloc = 0: temppoint = point
Do While temppoint > 8
temppoint = temppoint - 8: arrloc = arrloc + 1
Loop
pos = BitArray(arrloc, loc) And 2 ^ (temppoint - 1)
If pos = 0 And valu = True Then BitArray(arrloc, loc) = BitArray(arrloc, loc) + 2 ^ (temppoint - 1)
If pos <> 0 And valu = False Then BitArray(arrloc, loc) = BitArray(arrloc, loc) - 2 ^ (temppoint - 1)
setbit = getbit(point, loc)
End Function
getbit() pulls the value from the array as either zero (false) or non-zero (true)
setbit() takes a true or false and places it at the designated location
setbit(8, 100, True) Sets the 8th bit of the 100th value to true
getbit(8, 100) pulls the value out (as zero or nonzero...shouldn't be difficult to have the output as boolean true or false)
setbit(8, 100, False) Sets the same bit to false
It isn't clean code, my code is generally function over form, but it's something that could be worked on from to get what you need...and yeah, took a little longer than 5 minutes but I haven't worked with the bit level in ages :-)
Re: Boolean or Byte or Bit ?
Goodness gracious. That above code is doing implicit type casting all over the place, even to Doubles and back. I don't think that's what you want at all!
If we're dealing with bits in Bytes, here's some code I just hammered out (not even tested, but it should work):
Code:
Option Explicit
Public Property Get BitInByte(ByRef TheByte As Byte, ByVal Pos1to8 As Long) As Boolean
' Returns false if Pos1to8 is out of range.
Select Case Pos1to8
Case 1&: BitInByte = TheByte And CByte(1)
Case 2&: BitInByte = TheByte And CByte(2)
Case 3&: BitInByte = TheByte And CByte(4)
Case 4&: BitInByte = TheByte And CByte(8)
Case 5&: BitInByte = TheByte And CByte(16)
Case 6&: BitInByte = TheByte And CByte(32)
Case 7&: BitInByte = TheByte And CByte(64)
Case 8&: BitInByte = TheByte And CByte(128)
End Select
End Property
Public Property Let BitInByte(ByRef TheByte As Byte, ByVal Pos1to8 As Long, OnOff As Boolean)
' Does nothing if Pos1to8 is out of range.
Select Case Pos1to8
Case 1&: If OnOff Then TheByte = TheByte Or CByte(1) Else TheByte = TheByte And Not CByte(1)
Case 2&: If OnOff Then TheByte = TheByte Or CByte(2) Else TheByte = TheByte And Not CByte(2)
Case 3&: If OnOff Then TheByte = TheByte Or CByte(4) Else TheByte = TheByte And Not CByte(4)
Case 4&: If OnOff Then TheByte = TheByte Or CByte(8) Else TheByte = TheByte And Not CByte(8)
Case 5&: If OnOff Then TheByte = TheByte Or CByte(16) Else TheByte = TheByte And Not CByte(16)
Case 6&: If OnOff Then TheByte = TheByte Or CByte(32) Else TheByte = TheByte And Not CByte(32)
Case 7&: If OnOff Then TheByte = TheByte Or CByte(64) Else TheByte = TheByte And Not CByte(64)
Case 8&: If OnOff Then TheByte = TheByte Or CByte(128) Else TheByte = TheByte And Not CByte(128)
End Select
End Property
When dealing with a Byte, it's just easier to test it all out rather than involve any math at all. You can take the same approach with Integers if you'd like, just expand the Select Case statements on out.
And the only type casting that's being done in this code is the CByte functions, and I believe they're resolved by the compiler (not at runtime) ... and that's only because we don't have a Byte Literal Constant type.
-------
In the past few months, I've also posted some code to do something similar with Longs. However, I can't put my finger on it right now. I did use some math in that code, but it was all integer (Long) math. I could have done it as the above is done, but it's supposedly a bit quicker to bit-shift than to do those ANDs and ORs when dealing with Longs. And, you also have to deal with the sign bit when dealing with Longs. I'll try again to find it.
EDIT: I can't find it. I'm sure I posted it sometime in the last couple of years though. However, the above approach could even be taken with Longs if you wanted and it'd be better than using powers (which require conversion to Double, which isn't good). Just keep extending the Select statement.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Elroy
Goodness gracious. That above code is doing implicit type casting all over the place, even to Doubles and back. I don't think that's what you want at all!
If you meant my code, it doesn't use any other variable types directly WITH the byte array...it just uses a few different variables to handle other aspects of the functions. It's smaller, even smaller than your code, and it (currently) handles up to 32 bits of data per value (the same as a Long would, but using bytes). As I said below my code, I prefer function over form...the code works for what is needed, and it is succinct...I could probably have made it even shorter by removing the do/while and putting in a divisor/remainder calculation (which would also have slightly sped the process up as it doesn't need to loop around. It's essentially about 10 lines of code that performs both the get and set of the bit value, whereas both your code (which only works with up to 8 bytes rather than the required 12 and space for expansion in future up to 32) and the other one above. If you're going to say you will use select case for as many bits as the OP requires, it probably isn't going to be worth posting that...it might be at least semi-fast but I can see a program very quickly becoming bloated with the case options.
It was just a quick bit of coding and could do with dimming of some of the variables in use within those functions...but it gives the idea for the way in which I would do the job (and actually *does* the job), and would hopefully seed the idea for the OP to write their own based on it.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Shaggy Hiker
Does it take less time to access? I don't know how VB6 accesses data, but I don't think there is any advantage to shifting one byte into a register. I'm not even sure it's truly possible, which is probably why a Boolean is taking two bytes when it technically only needs a single bit.
Testing multiple bits in a bit field is certainly far more performant and far more efficient than using a set of Booleans for the same task. There are examples of this all over the place, the most well known being flags using by many Win32 API functions. CreateWindow's window styles come to mind or the many flags you can set using something like SetWindowLong.
However, it is not always worth it to use a bit field for boolean data. Lets use a contrived example. Let's say you have a function named IsOverLapping that takes two rectangles and returns a Boolean that tells you whether the two rectangles overlap. You can have it return a Byte which uses only a single bit. In this case however, it's not very efficient. This is because at the machine code level, you're still using an entire 32 bit or 64 bit register yet you are still requiring developers to pluck at it with bitwise operations to obtain the value of the least significant bit. It's more efficient to just use the whole register and a single instruction for testing.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Arnoutdv
Code:
Option Explicit
Private m_Bits(31) As Long
Public Sub InitBits()
Dim i As Long, lBits As Long
lBits = 1
For i = 0 To 30
m_Bits(i) = lValue
If i < 30 Then lBits = lBits * 2
Next i
m_Bits(31) = -2147483648#
End Sub
Public Sub SetBit(lValue As Long, ByVal lIndex As Long)
' Sets indicated bit to one, or ON.
Dim indx As Long, ofst As Long
indx = lIndex \ 32
ofst = lIndex And 31&
lValue(indx) = lValue(indx) Or m_Bits(ofst) 'turn the bit ON
End Sub
Public Function GetBit(lValue As Long, ByVal lIndex As Long) As Long
' Returns zero if the indicated bit is off, NON-ZERO if on.
Dim indx As Long, ofst As Long
indx = lIndex \ 32
ofst = lIndex And 31& 'posn MOD 32
GetBit = lValue And m_Bits(ofst)
End Function
Public Function IsBitSet(lValue As Long, ByVal lIndex As Long) As Boolean
' Returns zero if the indicated bit is off, NON-ZERO if on.
Dim indx As Long, ofst As Long
indx = lIndex \ 32
ofst = lIndex And 31& 'posn MOD 32
IsBitSet = (lValue And m_Bits(ofst)) <> 0
End Function
Public Sub ClearBit(lValue As Long, ByVal posn As Long)
' Sets indicated bit to zero, or OFF.
Dim indx As Long, ofst As Long
indx = posn \ 32
ofst = posn And 31 ' BITS0thru4 ' posn MOD 32
lValue = lValue And (Not m_Bits(ofst)) 'turn the bit OFF
End Sub
Public Function CountBits(lValue As Long) As Long
Dim lValue As Long
If lValue Then
If lValue = -1 Then
CountBits = CountBits + 32
Else
If lValue And &H1 Then CountBits = CountBits + 1
If lValue And &H2 Then CountBits = CountBits + 1
If lValue And &H4 Then CountBits = CountBits + 1
If lValue And &H8 Then CountBits = CountBits + 1
If lValue And &H10& Then CountBits = CountBits + 1
If lValue And &H20& Then CountBits = CountBits + 1
If lValue And &H40& Then CountBits = CountBits + 1
If lValue And &H80& Then CountBits = CountBits + 1
If lValue And &H100& Then CountBits = CountBits + 1
If lValue And &H200& Then CountBits = CountBits + 1
If lValue And &H400& Then CountBits = CountBits + 1
If lValue And &H800& Then CountBits = CountBits + 1
If lValue And &H1000& Then CountBits = CountBits + 1
If lValue And &H2000& Then CountBits = CountBits + 1
If lValue And &H4000& Then CountBits = CountBits + 1
If lValue And &H8000& Then CountBits = CountBits + 1
If lValue And &H10000 Then CountBits = CountBits + 1
If lValue And &H20000 Then CountBits = CountBits + 1
If lValue And &H40000 Then CountBits = CountBits + 1
If lValue And &H80000 Then CountBits = CountBits + 1
If lValue And &H100000 Then CountBits = CountBits + 1
If lValue And &H200000 Then CountBits = CountBits + 1
If lValue And &H400000 Then CountBits = CountBits + 1
If lValue And &H800000 Then CountBits = CountBits + 1
If lValue And &H1000000 Then CountBits = CountBits + 1
If lValue And &H2000000 Then CountBits = CountBits + 1
If lValue And &H4000000 Then CountBits = CountBits + 1
If lValue And &H8000000 Then CountBits = CountBits + 1
If lValue And &H10000000 Then CountBits = CountBits + 1
If lValue And &H20000000 Then CountBits = CountBits + 1
If lValue And &H40000000 Then CountBits = CountBits + 1
If lValue And &H80000000 Then CountBits = CountBits + 1
End If
End If
End Function
Very valuable code. Your code is very helpful for me to achieve 32 Bit-Options. Thank you, Arnoutdv.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
SmUX2k
Very quick bit of code that seems to work for me, and much smaller than the one offered above:
Code:
Public BitArray(3, 1000000) As Byte
Public Function getbit(point As Single, loc As Double)
arrloc = 0: temppoint = point
Do While temppoint > 8 'Gets the position along the dimensions
temppoint = temppoint - 8: arrloc = arrloc + 1
Loop
getbit = BitArray(arrloc, loc) And 2 ^ (temppoint - 1)
End Function
Public Function setbit(point As Single, loc As Double, valu As Boolean)
arrloc = 0: temppoint = point
Do While temppoint > 8
temppoint = temppoint - 8: arrloc = arrloc + 1
Loop
pos = BitArray(arrloc, loc) And 2 ^ (temppoint - 1)
If pos = 0 And valu = True Then BitArray(arrloc, loc) = BitArray(arrloc, loc) + 2 ^ (temppoint - 1)
If pos <> 0 And valu = False Then BitArray(arrloc, loc) = BitArray(arrloc, loc) - 2 ^ (temppoint - 1)
setbit = getbit(point, loc)
End Function
getbit() pulls the value from the array as either zero (false) or non-zero (true)
setbit() takes a true or false and places it at the designated location
setbit(8, 100, True) Sets the 8th bit of the 100th value to true
getbit(8, 100) pulls the value out (as zero or nonzero...shouldn't be difficult to have the output as boolean true or false)
setbit(8, 100, False) Sets the same bit to false
It isn't clean code, my code is generally function over form, but it's something that could be worked on from to get what you need...and yeah, took a little longer than 5 minutes but I haven't worked with the bit level in ages :-)
Very good idea. Your code does take up less memory. Thank you, SmUX2k.
Re: Boolean or Byte or Bit ?
Quote:
Originally Posted by
Elroy
Goodness gracious. That above code is doing implicit type casting all over the place, even to Doubles and back. I don't think that's what you want
at all!
If we're dealing with bits in Bytes, here's some code I just hammered out (not even tested, but it should work):
Code:
Option Explicit
Public Property Get BitInByte(ByRef TheByte As Byte, ByVal Pos1to8 As Long) As Boolean
' Returns false if Pos1to8 is out of range.
Select Case Pos1to8
Case 1&: BitInByte = TheByte And CByte(1)
Case 2&: BitInByte = TheByte And CByte(2)
Case 3&: BitInByte = TheByte And CByte(4)
Case 4&: BitInByte = TheByte And CByte(8)
Case 5&: BitInByte = TheByte And CByte(16)
Case 6&: BitInByte = TheByte And CByte(32)
Case 7&: BitInByte = TheByte And CByte(64)
Case 8&: BitInByte = TheByte And CByte(128)
End Select
End Property
Public Property Let BitInByte(ByRef TheByte As Byte, ByVal Pos1to8 As Long, OnOff As Boolean)
' Does nothing if Pos1to8 is out of range.
Select Case Pos1to8
Case 1&: If OnOff Then TheByte = TheByte Or CByte(1) Else TheByte = TheByte And Not CByte(1)
Case 2&: If OnOff Then TheByte = TheByte Or CByte(2) Else TheByte = TheByte And Not CByte(2)
Case 3&: If OnOff Then TheByte = TheByte Or CByte(4) Else TheByte = TheByte And Not CByte(4)
Case 4&: If OnOff Then TheByte = TheByte Or CByte(8) Else TheByte = TheByte And Not CByte(8)
Case 5&: If OnOff Then TheByte = TheByte Or CByte(16) Else TheByte = TheByte And Not CByte(16)
Case 6&: If OnOff Then TheByte = TheByte Or CByte(32) Else TheByte = TheByte And Not CByte(32)
Case 7&: If OnOff Then TheByte = TheByte Or CByte(64) Else TheByte = TheByte And Not CByte(64)
Case 8&: If OnOff Then TheByte = TheByte Or CByte(128) Else TheByte = TheByte And Not CByte(128)
End Select
End Property
When dealing with a Byte, it's just easier to test it all out rather than involve any math at all. You can take the same approach with Integers if you'd like, just expand the Select Case statements on out.
And the only type casting that's being done in this code is the CByte functions, and I believe they're resolved by the compiler (not at runtime) ... and that's only because we don't have a Byte Literal Constant type.
-------
In the past few months, I've also posted some code to do something similar with Longs. However, I can't put my finger on it right now. I did use some math in that code, but it was all integer (Long) math. I could have done it as the above is done, but it's supposedly a bit quicker to bit-shift than to do those ANDs and ORs when dealing with Longs. And, you also have to deal with the sign bit when dealing with Longs. I'll try again to find it.
EDIT: I can't find it. I'm sure I posted it sometime in the last couple of years though. However, the above approach could even be taken with Longs if you wanted and it'd be better than using powers (which require conversion to Double, which isn't good). Just keep extending the Select statement.
Very nice code, it's easy to extend to Integer and Long. Select-Case is indeed simple and effective. Thank you, Elroy.
Re: Boolean or Byte or Bit ?
Sorry for the late reply. Thank you to everyone involved in this thread.
Arnoutdv, SmUX2k and Elroy offer three different types of codes, each with its own unique value. I combined the advantages of the above three pieces of code and put together a piece of code that fully meets my needs:
Code:
Public Function GetBit(ByRef nBitOptions As Integer, ByVal nBitIndex As Long) As Boolean
'--- Returns false if nBitIndex (1 to 16) is out of range.
Select Case nBitIndex
Case 1&: GetBit = nBitOptions And &H1
Case 2&: GetBit = nBitOptions And &H2
Case 3&: GetBit = nBitOptions And &H4
Case 4&: GetBit = nBitOptions And &H8
Case 5&: GetBit = nBitOptions And &H10
Case 6&: GetBit = nBitOptions And &H20
Case 7&: GetBit = nBitOptions And &H40
Case 8&: GetBit = nBitOptions And &H80
Case 9&: GetBit = nBitOptions And &H100
Case 10&: GetBit = nBitOptions And &H200
Case 11&: GetBit = nBitOptions And &H400
Case 12&: GetBit = nBitOptions And &H800
Case 13&: GetBit = nBitOptions And &H1000
Case 14&: GetBit = nBitOptions And &H2000
End Select
End Function
Public Sub SetBit(ByRef nBitOptions As Integer, ByVal nBitIndex As Long, newValue As Boolean)
'--- Does nothing if nBitIndex (1 to 16) is out of range.
Select Case nBitIndex
Case 1&: If newValue Then nBitOptions = nBitOptions Or &H1 Else nBitOptions = nBitOptions And Not &H1
Case 2&: If newValue Then nBitOptions = nBitOptions Or &H2 Else nBitOptions = nBitOptions And Not &H2
Case 3&: If newValue Then nBitOptions = nBitOptions Or &H4 Else nBitOptions = nBitOptions And Not &H4
Case 4&: If newValue Then nBitOptions = nBitOptions Or &H8 Else nBitOptions = nBitOptions And Not &H8
Case 5&: If newValue Then nBitOptions = nBitOptions Or &H10 Else nBitOptions = nBitOptions And Not &H10
Case 6&: If newValue Then nBitOptions = nBitOptions Or &H20 Else nBitOptions = nBitOptions And Not &H20
Case 7&: If newValue Then nBitOptions = nBitOptions Or &H40 Else nBitOptions = nBitOptions And Not &H40
Case 8&: If newValue Then nBitOptions = nBitOptions Or &H80 Else nBitOptions = nBitOptions And Not &H80
Case 9&: If newValue Then nBitOptions = nBitOptions Or &H100 Else nBitOptions = nBitOptions And Not &H100
Case 10&: If newValue Then nBitOptions = nBitOptions Or &H200 Else nBitOptions = nBitOptions And Not &H200
Case 11&: If newValue Then nBitOptions = nBitOptions Or &H400 Else nBitOptions = nBitOptions And Not &H400
Case 12&: If newValue Then nBitOptions = nBitOptions Or &H800 Else nBitOptions = nBitOptions And Not &H800
Case 13&: If newValue Then nBitOptions = nBitOptions Or &H1000 Else nBitOptions = nBitOptions And Not &H1000
Case 14&: If newValue Then nBitOptions = nBitOptions Or &H2000 Else nBitOptions = nBitOptions And Not &H2000
End Select
End Sub
It feels very good to learn different knowledge points from different people, and then sum up a solution that is completely suitable for the actual project needs.