Constant Increments

J

Jack Leach

Many constants in programming are defined with values that, when any
combination of their sum is procuded, will add to a unique number, for use in
contencating values to supply one or more constants by reading a single
value...

For instance, constants declared as 1, 2, 4, 8, 16, 32 etc can all be added,
in any combination, and each combination will produce a unique sum which will
tell which of the subset were added.

Two questions:
1) what is this concepted officially called?
2) is there an implementation standard for this? I assume that there's a
function already written somewhere that will take a given sum and break it
down to components.

I'm fairly certain I can figure this out on my own, shouldn't be all that
difficult, but I assume there is some standard method, and if so I would like
to adopt it.

Any pointers? Thanks,

--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)
 
K

Ken Snell MVP

Essentially, what you're doing is setting the bits of a byte in this
situation. I don't recall what the official term is, but essentially it's
binary storage.
 
B

Banana

They may have different names but I usually call them bitwise flags.

Basically you'd take an integer as a argument and use a certain value to
set the flags accordingly.

Sample:

Public Enum MyBitFlags
TCP = 1
NamedPipe = 2
StayAlive = 4
AutoReconnect = 8
Encryption = 16
End Enum


'Set a bit flag
Public Function SetIt(int As MyBitFlags, newint As MyBitFlags) As MyBitFlags

int = int Or newint

Setit = int

End Function

'Clear a bit flag
Public Function ClearIt(int As MyBitFlags, oldint As MyBitFlags) As
MyBitFlags

int = int And (Not newint)

ClearIt = int

End Function

'Test if a flag is set

Public Function TestIt(int As MyBitFlags, testint As MyBitFlags) As
MyBitFlags

TestIt = (int And testint)

End It

'Pass multiple arguments in one go
Public Sub CallIt()

Doit(TCP + StayAlive + Encryption)

End Sub

Public Sub DoIt(int As MyBitFlags)

....

End Sub



How does that work? As name implies they're bitwise. 1,2,4,8,16 are not
accidental; they are represent of binary's value position:

Assuming a byte is used here: (In reality, all Enums will be a long
integer so that's actually 32 bit, not 8 bit)

00000000 = 0
00000001 = 1
00000010 = 2
00000100 = 4
00001000 = 8
00010000 = 16

You can see that each bit occupies a different position in the byte so
we can use it to set it on/off by using boolean arthimetric as expressed
in VBA's Or, And/Not, as well other operators. We can then use each bit
to generate a complex combination of information. It's a common
technique in low-level programming, but I find it fairly rare in VBA,
because it only makes sense when we have several options that may be
valid in various combinations, which is less likely setup but that
doesn't mean it can't be done. I've actually used it once in a project
where they had several rules that may be valid or not valid and rather
than weighing down with several boolean variables (which will consume 2
bytes per variable), I can use a single variable to hold all possible
rules that are in effect and validate that the combination are valid
before running the reports.

HTH.
 
J

Jack Leach

Banana,

This an excellent description and very helpful. Thank you for the functions
and the explanation.


Intend to use this for tracking various certification requirements for
purchases, and don't expect to have to go very deep (8bits should be
sufficient). Just for the record though, do you happen to have a pointer to
the numeric values of all bits for a 32bit operator? Still not sure how to
term my searches...

0, 1, 2, 4, 8, 16, 32, 64, 128, 248, 496 etc

for numbers past 0, is this always the previous number * 2 or is there some
in between that I'm missing...


thanks again,



--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)
 
D

Dirk Goldgar

Jack Leach said:
Banana,

This an excellent description and very helpful. Thank you for the
functions
and the explanation.


Intend to use this for tracking various certification requirements for
purchases, and don't expect to have to go very deep (8bits should be
sufficient). Just for the record though, do you happen to have a pointer
to
the numeric values of all bits for a 32bit operator? Still not sure how
to
term my searches...

0, 1, 2, 4, 8, 16, 32, 64, 128, 248, 496 etc

for numbers past 0, is this always the previous number * 2 or is there
some
in between that I'm missing...


It's always the previous number * 2, because it's always powers of two. So,
canb easily calculate all the bits in a 32-bit value (numbered 0 to 31) like
this:

For i = 0 to 31 : ?2^i : Next I
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
2147483648
 
J

Jack Leach

one more question... what forumla does one use to go about finding if a
specific value is part of the bit?

If I have:

Enum eMatCertReqs
ChemTest = 1
PhysTest = 2
RadTest = 4
DyePenTest = 8
End Enum

and I store a value of 11 in my field, what method would be used to parse
the value of 11 to check for, say, a requirement for a Radiology Test? (or
any others).

Is there a formula for this? I could manually figure it out but that's
going to take a little work I'd like to avoid if possible...




--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)
 
D

Dirk Goldgar

Jack Leach said:
one more question... what forumla does one use to go about finding if a
specific value is part of the bit?

If I have:

Enum eMatCertReqs
ChemTest = 1
PhysTest = 2
RadTest = 4
DyePenTest = 8
End Enum

and I store a value of 11 in my field, what method would be used to parse
the value of 11 to check for, say, a requirement for a Radiology Test? (or
any others).

Is there a formula for this? I could manually figure it out but that's
going to take a little work I'd like to avoid if possible...


If (MyFieldValue And RadTest) <> 0 Then
' a radiology test is required
End If
 
J

Jack Leach

from help: "The And operator also performs a bitwise comparison of
identically positioned bits in two numeric expressions"

Never knew that.

Thanks a bunch for the help guys! Been curious about this one for a long
time, glad to have it under the thumb now.

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)
 
B

Banana

As suggested in the TestIt function in my previous example, you use And
operator to test for a specific value.

Public Function TestIt(int As MyBitFlags, testint As MyBitFlags) As
MyBitFlags

TestIt = (int And testint)

End It


Note that you can pass in multiple test in one go. Say you require 3
tests to be already taken before 4th test can be taken, and 3 test has
the following values 2, 8, and 32 then the sum is 42. We would do this:

If Testit(MyTestStanding, Test2 + Test8 + Test32) = Test2 + Test8 +
Test32 Then

or

If TestIt(MyTestStanding, 42) = 42 Then

which are equivalent.

The And operator will return whatever bitwise matches in same bit
position and you can then deduct what is the missing test and act
accordingly. For one bit test, it's really a matter of testing for
True/False.
 
J

Jack Leach

Just wanted to say thanks again... this is a truely amazing technique.

Banana, funny you mention that this low-level programming technique isn't
seen often in vba. In my case, in all the different situations where I need
to track what kinds of required paperwork I need, from customer quality
report furnishing to production process and tracking and purchasings
documentation required for incoming items, I expect to be able to remove
approximately 40 or 50 various fields throughout my shop management app. And
that's just in standard documentation requirements!

The only drawback that I can see is the inability to expressly identify
requirements when looking at the raw data through developer's eyes. But the
payoff of consolidating 40 to 50 table fields into 8 or 10 long integer
fields is obviously a no-brainer.

This is the best new concept I've picked up on in years. Many thanks again!

--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)
 
B

Banana

Few points.

The official documentation (well, Access's documentation, rather than
Jet's documentation) states that Yes/No fields are one bit, which led to
speculation that it may be actually packed (e.g. 8 Yes/No fields
actually occupy only one byte although, though adding one more Yes/No
field will now require one new byte for the row's storage.) However,
it's not all that clear whether Yes/No actually is packed or not and
there is some reasons to think it's not packed.

For more information than you ever could possibly want and more:
http://www.access-programmers.co.uk/forums/showthread.php?t=152490

Especially Post #12.

Next, I'm a bit worried about the structure. You said you have 40 to 50
fields which will be now a long integer. While this is indeed a saving,
I'm not so sure this is actually normalized and suggest to me this may
be in fact a Many-Many relationship which requires breaking the 40 to 50
fields into a lookup table with 40 to 50 rows and a junction table.

This is purely a guess but I want to make sure we do not forget the
principle that normalization and database design should be driving the
application design, not some fancy low-level programming techniques
which can certainly be very relevant in different problem domain and
possibly have a place even in Access application but shouldn't be a
substitute for a proper normalization.

Hope that helps a bit. :)
 
S

Stuart McCall

Jack Leach said:
from help: "The And operator also performs a bitwise comparison of
identically positioned bits in two numeric expressions"

Never knew that.

Thanks a bunch for the help guys! Been curious about this one for a long
time, glad to have it under the thumb now.

FWIW I've always called them bitfields and I set bits by ORing in the
values, not adding them. Example:

Debug.Print 2 Or 16 Or 128
Result 146

but if one of the values is Null for whatever reason:

Debug.Print 2 Or Null Or 128
Result 130

whereas:

Debug.Print 2 + Null + 128
Result Null


The way I've always remembered this kinda thing is:

OR them in
AND them out

I only use this technique in code, never as data storage, for the reason
Banana pointed out.

HTH a bit
 
B

Banana

Good points, Stuart.

One more good reason for using Or is to avoid messing up the bit flags
when one is uncertain if the flag has been already set.

?2 Or 0
2

?2 + 0
2

?2 Or 2
2

?2 + 2
4

It works in reverse as well:

?3 And (Not 2)
1

?1 And (Not 2)
1

Subtracting 2 would mess up the bitfield set to 1 so in this sense,
Or'ing and And/Not'ing are "safe" ways to set or clear a bit flag.
 
S

Stuart McCall

Banana said:
Good points, Stuart.

One more good reason for using Or is to avoid messing up the bit flags
when one is uncertain if the flag has been already set.
<snip>

Good point yourself. Hadn't thought about that. But since I always use Or I
hadn't run into the problem.

Thanks
 
D

David H

I assume that by certification that you're looking at certain qualities
associated with the purchse?

Personally, I'd be a bit leery with using an approach like this for that
type of work. While today there might only be 5 or 6 conditions that you need
to track, it sets things up to be very difficult if those 5 or 6 conditions
become 10 or 12.

I am a *HUGE* believer in never, never, never boxing in functionality. I
cannot think of a single instance were someone has approached something from
a most-flexible standpoint where its turned around and bit them in the ass.
But I can think of times where limitations have come back to screw things up.
Case in point, the hard limit of transactions in the application that Comair
used which resulted in their system shutting down during the holiday rush a
few years back.

http://www.computerbytesman.com/security/comair.htm

Even if its something where you build a class to validate what ever you need
to do, the class can be designed in such a way that expanding it isn't the
big of an effort.
 
S

Stuart McCall

Banana, funny you mention that this low-level programming technique isn't
seen often in vba

There are a few places where this occurs in VBA and one is the Buttons
parameter for MsgBox.

Another is the Shift parameter for MouseDown/Up events.
 
B

Banana

David said:
Even if its something where you build a class to validate what ever you need
to do, the class can be designed in such a way that expanding it isn't the
big of an effort.

Ayup.

When I think about it, I suppose one way to make it work with a
normalized many-many relationship as I described earlier is instead of
using an autonumber for primary key, assign powers of 2 as a primary
key, then enforce an unique index over the junction table so no single
entity will have duplicate bit values.

We then can retrieve the full bit set by doing a SUM(pkcol) query for
the selected entity. Taking it a step further, we can then join the
query against a one-column, one-row table... call it tblValidator where
we set the bit flag. Say we require bit flag for 2, 16 and 64 to be
satisfied, so we put in 82 in that table:

SELECT t.*
FROM (SELECT EntityID, SUM(pkID) bitflags
FROM jctValues
GROUP BY EntityID) t
INNER JOIN tblValidator v
ON t.bitflags = v.validateflags;

This setup allows us to apply standard queries against the participating
tables in many-many relationship while preserving the functionality of
bitflags for use in VBA validation, and adding a new flag is easy as
adding an appropriate row in the lookup table with appropriate value for
the primary key.

Unfortunately, we've lost the saving of a single integer field with this
setup as each 'match' for an entity with a certain field occupy a single
row in the junction table each, but I think this is a necessary
sacrifice to maintain the normalization, which basically is what
database design is all about. At least as long we're not entering data
warehousing which is entirely different horse!
 
D

David H

I assume that by certification that you're looking at certain qualities
associated with the purchse?

Personally, I'd be a bit leery with using an approach like this for that
type of work. While today there might only be 5 or 6 conditions that you need
to track, it sets things up to be very difficult if those 5 or 6 conditions
become 10 or 12.

I am a *HUGE* believer in never, never, never boxing in functionality. I
cannot think of a single instance were someone has approached something from
a most-flexible standpoint where its turned around and bit them in the ass.
But I can think of times where limitations have come back to screw things up.
Case in point, the hard limit of transactions in the application that Comair
used which resulted in their system shutting down during the holiday rush a
few years back.

http://www.computerbytesman.com/security/comair.htm

Even if its something where you build a class to validate what ever you need
to do, the class can be designed in such a way that expanding it isn't the
big of an effort.
 
D

David H

"...In my case, in all the different situations where I need
to track what kinds of required paperwork I need, from customer quality
report furnishing to production process and tracking and purchasings
documentation required for incoming items, "

Whoa! That actually raises a huge red flag . How exactly is your database
structured? Why aren't you using a child table to show which documents are
required and have been received for a particular purchase? It is entirely
possible to design a database so that when a new purchase is added that the
child records for the required documents are automatically created.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top