Solved

Bitwise Operations on Single, Double or Decimal types ?

Posted on 1998-03-09
13
493 Views
Last Modified: 2008-02-01
Is it possible to perform bitwise operations on types other than byte, integer or long ?

eg.

dim x as Double

x = 345678890 ' or any large number

? x And 2 ^ 60

This is currently resulting in an overflow.
0
Comment
Question by:woka
  • 7
  • 6
13 Comments
 
LVL 8

Expert Comment

by:mrmick
ID: 1458736
You bet.

But you can't check for a bit that doesn't exist.  You must remember the size of the data type:

Byte = 8 bits
Integer = 16 bits
Long = 32 bits
Double = 64 bits

*** AND ***
When you're checking the sign bit of an integer or long - the bit value must be negative.  For example, to check bit 15 of an integer... Use the following:

If MyInt and 1(2^15) then
  Msgbox "Bit is set"
else
  Msgbox "Bit is clr"
endif

0
 
LVL 8

Expert Comment

by:mrmick
ID: 1458737
Whoops, that last example should have been:



If MyInt and -(2^15) then
  Msgbox "Bit is set"
else
  Msgbox "Bit is clr"
endif
0
 
LVL 2

Author Comment

by:woka
ID: 1458738
Given your answer, the example I gave should work.  Instead it results in an overflow error.  Any more ideas ?

0
 
LVL 8

Expert Comment

by:mrmick
ID: 1458739
Sorry woka, the bit values of a floating type (double or single) are comprised of a sign bit, mantissa bits and exponent bits.  You really can only effectively test bit values of integers.

While Bit 60 exists, 2^60 is a larger value than a double can store precisely.  To answer your question, Bit 60 in the 64 bits that make up a double would have to be tested as follows:

If 2 ^ 28 And x Then
  Print "Bit 60 is Set"
Else
  Print "Bit 60 is Clr"
End If

0
 
LVL 2

Author Comment

by:woka
ID: 1458740
Sorry to keep coming back about this (not sure if I should keep reopening the question either, is that the right protocol) but how did you derive the 28 in 2 ^ 28 ?

0
 
LVL 8

Accepted Solution

by:
mrmick earned 200 total points
ID: 1458741
Whoops, I that was the 64th bit I set.  Here is example code that sets the 60th bit and displays the resulting number in the debug (immediate) window.  Create a new project and paste this code into the project.

'The eight bytes that make up a double
Private Type DoubleBytes
  B0 As Byte
  B1 As Byte
  B2 As Byte
  B3 As Byte
  B4 As Byte
  B5 As Byte
  B6 As Byte
  B7 As Byte
End Type

'A Double
Private Type MyDouble
   dbl As Double
End Type

Private Sub Form_Load()

Dim db As DoubleBytes
Dim mydbl As MyDouble

'Set the 60th bit (range = 0 to 63)
db.B7 = 16

'Copy the bytes to the double.
LSet mydbl = db

'Display the result
Debug.Print mydbl.dbl

End Sub

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 2

Author Comment

by:woka
ID: 1458742
Excellent !!  Thanks for your help with this, it's going to make my life a lot easier.  FYI, the application I am using it with is taking data from a UPS where each bit in a series of bytes represents an event.  There are a total of 74 possible events.  While I can use a UDT to manipulate the info, I also have to pass it using COM where UDT's are a no go.  Passing a variant containing a Decimal data type is a lot more practical than having to deal with a bunch of bytes or integers or longs (I've had a quick bash modifying your code and it doesn't really like me using a variant, but I'll find a way around this).

I spent some time last night pouring over some old fortran doco on IEEE formats but didn't really get anywhere.  The solution you've given me will help imensely (sp?).  Thanks again.

PS.  Isn't LSet a useful little thing !

0
 
LVL 8

Expert Comment

by:mrmick
ID: 1458743
No problem, If you let me know how many bits are in your data type, I can probably show you an even easier way of passing the data.  Furthermore, you're best bet is to create a class to handle this.  I have an appointment right now (will take most of the evening), but when I return, If you've given me more details, I'll try to work out an example for you.  Give me an example of your call passing the data too.
0
 
LVL 2

Author Comment

by:woka
ID: 1458744
I am planning on using a double or decimal data type.  In a variant, the doco states that double is 16 bytes and decimal is 12 or 14 bytes depending on where you look.  It would be nice to use a "normal" way of checking bits like:

if varDouble And &H4000000 then

but since this will (I suspect) result in overflow I suppose a series of functions as follows would work best:

varDecimal = SetBit(varDecimal as Variant, BitNumber as Integer, bSet as Boolean)

bSet = IsBitSet(varDecimal as Variant, BitNumber as Integer)

The variable (I've been using a variant with a long data type for testing) is already contained within a class (and collection) with all the other UPS data.  Is this what you meant ?

TIA

0
 
LVL 8

Expert Comment

by:mrmick
ID: 1458745
I was going to carry it a bit further (no pun intended).  For example, if bits 0 - 5 indicated the Week of the Year, and bit 6 indicated AM or PM, I might expose the following properties:

'Class level array declaration.
Dim Bits(0 to 15) as byte ‘Array of bytes containing 16 bytes of bits (128 bits)

Property Get WeekOfYear() As Long 'Could be Integer, or even Byte
   DayOfWeek = Bits(0) And &H3F
End Property

Property Let DayOfWeek(NewValue As Long)
   Bits(0) = (Bits(0) And &HC0) Or (NewValue And &H3f)
End Property

Property Get IsAM() As Boolean
   IsAM = Bits(0) And &H40H
End Property

Property Let IsAm(NewValue as boolean)
   Bits(0) = (Bits(0) And &HBF) Or (NewValue And &H40)
End Property

And so on...

I still have no idea what method you’re using to pass the bit info so I can’t make a suggestion.  If you posted the method you’re using to pass the bit data, I would likely see a good solution to that problem.

0
 
LVL 2

Author Comment

by:woka
ID: 1458746
This may need a bit of explanation.

The UPS is sending information to the PC (via a serial port) in ASCII packets.  There are several different types of packets containing different information, but the one I'm dealing with here is as follows:

<SOH><HEADER><STX>1000100010001001<ETX>

Each 1 or 0 represents an event currently happening on the UPS. eg. The first 1 represents the event "Mains Failure".  If it is 1, the mains supply has failed and if it's 0 the mains is OK.

I'm just taking the ASCII string and storing it in a variable where each bit represents an event.

The method used to pass the info is like this:

Sub UpdateEvents(vEvents as Variant)

The variant would presumably be of type double or decimal.

Given that each bit is has an individual purpose rather than being combined with other bits, I'm not sure the method you have shown above is applicable.

Having said that, the penny has dropped with what you are doing and I can see a lot of applications for it that I wouldn't have thought to deal with that way before.  I obviously didn't write enough Fortran !

Am I on the right track ?  Let me know if you still think there is an application for what you presented above.  TIA.
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1458747
Hmmm... I think so (by the way, I haven't written any Fortran since 1982).  I think I'm going to put this to rest...  I didn't realize you were communicating through a serial port; I thought you were working with a DLL interface that handled communications with the UPS.  My mistake.

Until next time...
0
 
LVL 2

Author Comment

by:woka
ID: 1458748
Thanks again for your input.  It's been really valuable, not to mention how quick your responses have been.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now