[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

Bitwise Ops On Large Numbers

BeeJ

10/18/2011 2:37:00 AM

How do I do bit ops OR AND XOR NOT on large numbers?

e.g. This fails at the Or
Dim val1 As Variant
Dim val2 As Variant
Dim val3 As Variant

val1 = CDec(2 ^ 33)
val2 = CDec(1)
val3 = CDec(val1 Or val2)

Debug.Print val3


33 Answers

ralph

10/18/2011 4:54:00 AM

0

On Mon, 17 Oct 2011 19:36:34 -0700, BeeJ <nospam@spamnot.com> wrote:

>How do I do bit ops OR AND XOR NOT on large numbers?
>
>e.g. This fails at the Or
> Dim val1 As Variant
> Dim val2 As Variant
> Dim val3 As Variant
>
> val1 = CDec(2 ^ 33)
> val2 = CDec(1)
> val3 = CDec(val1 Or val2)
>
> Debug.Print val3
>

Not a question of "large numbers" but simply that you are trying to do
a bitwise operation on a float. What meaningful result is to even be
expected?

If you need to perform a bitwise operations using float operands you
first need to convert the numbers to a character string or to some
other pattern of discrete values that are both of the same size.

eg:
decimal 2.13
decimal 134.6
might become ...
string "00213" or &213&
string "13460" or &13460&

Really large numbers might be converted to some object made up of more
than one value like a 'Long Long' for example that provides its own
bitwise methods. But that is another story.

Bottom line don't use bitwise operators with anything that uses
"binary or object representation" - only use them on data types that
have "value representation".

-ralph

BeeJ

10/18/2011 11:13:00 PM

0

I need to maintain in one string variable the state True/False of many
"columns". Right now, 32 is the max number of columns due to the
limitations of AND OR XOR NOT because I am compressing the column info
into the bit positions of each character.
I am stuck having to use a string as the variable so my bitwise
manipulation sub all work with that. And they work just fine.
However, I need to be able to expand the number of possible columns.
In trying to minimize memory space, I am using a variable width
(string) as the value. So if nothing is selected (or whatever), the
string is empty. Trying to use the same method as I am but adding
additional gets messy e.g. token,token... where the token is the
value. each toke hadles up to the max allowed by the bit operators.
If I had bit operators that worked on larger values then the mess would
reduce to just one token.
So now maybe I need to figure out how to work bitwise on a string of
characters, each character holding a bits. So I would have to break
down each character into bits and manipulate each bit or maybe byte
individually. Maybe convert the string to a byte array, manipulate,
then convert byte array back to string.
The string is never readable as text, just bit storage, manipulate bits
OR AND XOR NOT, and test bit state.
Got any sample code that can get me going?
Or at least some coding details that will help me start?


Thorsten Albers

10/19/2011 12:15:00 AM

0

BeeJ <nospam@spamnot.com> schrieb im Beitrag
<j7l15g$epg$1@speranza.aioe.org>...
> I need to maintain in one string variable the state True/False of many
> "columns". Right now, 32 is the max number of columns due to the
> limitations of AND OR XOR NOT because I am compressing the column info
> into the bit positions of each character.

An array of integer values gives you as many bits as you need to
manipulate. Best performance should be reached with an array of Long = 32
bit values.
E.g. with single bits (not tested, coded 'on the fly'):

Const MAXCOLS As Long = 200000
Const BITSPERLONG As Long = 32
Const BITSPERCOLUMN As Long = 1
Const BITWIDTH As Long = BITSPERLONG * BITSPERCOLUMN

Dim alBits() As Long
Dim lCount As Long

lCount = MAXCOLS \ BITWIDTH
If (MAXCOLS Mod BITWIDTH) Then lCount = lCount + 1
ReDim alBits(0 to (lCount - 1)) As Long

....

Dim lIndex As Long, lMask As Long, lBits As Long

lIndex = lColumn \ BITWIDTH
lMask = lColumn Mod BITWIDTH

lBits = alBits(lIndex)
If (lBits And lMask) Then
' Bit for column n is set; e.g. clear the bit
alBits(lIndex) = lBits And (Not lMask)
Else
' Bit for column n is not set; e.g. set the bit
alBits(lIndex) = lBits Or lMask
End If

--
Thorsten Albers

gudea at gmx.de

BeeJ

10/19/2011 11:14:00 PM

0

I have worked out an almost infinte (in VB6 term) wide bit maping
capability in one variable.
Since I need it to store in a string, it manipulates bits in the
string.
String width is only as needed to hold the most significant bit.
I now have BitSet, BitReset, BitFlip, BitClear functions and a compress
to remove leading detritus.
Turns out to be pretty fast, in the low uSecs per op.
Way faster than I need.
Thanks for all your feedback that really got me thinking.


Thorsten Albers

10/20/2011 1:57:00 AM

0

BeeJ <nospam@spamnot.com> schrieb im Beitrag
<j7nljb$2h4$1@speranza.aioe.org>...
> I have worked out an almost infinte (in VB6 term) wide bit maping
> capability in one variable.
> Since I need it to store in a string, it manipulates bits in the
> string.
> String width is only as needed to hold the most significant bit.
> I now have BitSet, BitReset, BitFlip, BitClear functions and a compress
> to remove leading detritus.
> Turns out to be pretty fast, in the low uSecs per op.
> Way faster than I need.
> Thanks for all your feedback that really got me thinking.

Lets hope that you have only used ChrW$(), ChrB$(), AscW() and AscB()
because Chr$() and Asc() may give you wrong values!

I really can't see any advantage in using a string for this instead of a
byte-, integer-, or long-array! Although a string somehow is nothing else
but an integer-array, accessing the characters of a string takes more time
than accessing the items of an array. Note that any x =
Mid$()/Left$()/Right$() (i.e. also e.g. AscW(Mid$(...))) first needs to
create the sub-string which is more time consuming than e.g. x =
aiValue%(n).

--
Thorsten Albers

gudea at gmx.de

BeeJ

10/23/2011 9:14:00 PM

0

Thorsten Albers brought next idea :
> BeeJ <nospam@spamnot.com> schrieb im Beitrag
> <j7nljb$2h4$1@speranza.aioe.org>...
>> I have worked out an almost infinte (in VB6 term) wide bit maping
>> capability in one variable.
>> Since I need it to store in a string, it manipulates bits in the
>> string.
>> String width is only as needed to hold the most significant bit.
>> I now have BitSet, BitReset, BitFlip, BitClear functions and a compress
>> to remove leading detritus.
>> Turns out to be pretty fast, in the low uSecs per op.
>> Way faster than I need.
>> Thanks for all your feedback that really got me thinking.
>
> Lets hope that you have only used ChrW$(), ChrB$(), AscW() and AscB()
> because Chr$() and Asc() may give you wrong values!
>
> I really can't see any advantage in using a string for this instead of a
> byte-, integer-, or long-array! Although a string somehow is nothing else
> but an integer-array, accessing the characters of a string takes more time
> than accessing the items of an array. Note that any x =
> Mid$()/Left$()/Right$() (i.e. also e.g. AscW(Mid$(...))) first needs to
> create the sub-string which is more time consuming than e.g. x =
> aiValue%(n).

Yeah, so how would you implement that?
My string is a string of bytes, variable width. Each byte represents 8
bit positions.
So for example, a string of 11 bytes represents 88 bits.
How do you use something else that is that compact?

So for example, each bit might represent one of 88 columns in a grid.
If I am only working on the first few columns, then the string LenB()
is even smaller.
Bit Set indicating cell selected.

It only takes around 11uSec to set or reset or test a bit state.

Show me some examples of your way.


Jim Mack

10/23/2011 10:48:00 PM

0

>
> Yeah, so how would you implement that?
> My string is a string of bytes, variable width. Each byte represents 8
> bit positions.
> So for example, a string of 11 bytes represents 88 bits.
> How do you use something else that is that compact?

VB strings are not strings of bytes, they're BSTR -- strings of Unicode
characters, which are 16 bits. Externally they may appear to be 8 bits
but the transform is subject to distortion in certain ranges, which is
why Thorsten cautioned about Chr$(). Plus, each string has a 32-bit
size prefix, so your 88 bits becomes 208 bits of storage.

Using long integers would give you (up to) 32 bits of data for each 32
bits of storage, and would not be subject to Unicode distortion.

If you use arrays there will be additional storage overhead (the
SAFEARRAY structure). Larger arrays minimize that impact. Whatever
logic you're using to compute the character position within the string
would work as well for long integer (or even byte) arrays, and should
be much much faster than strings.

--
Jim


BeeJ

10/23/2011 11:57:00 PM

0

Jim Mack wrote :
>>
>> Yeah, so how would you implement that?
>> My string is a string of bytes, variable width. Each byte represents 8 bit
>> positions.
>> So for example, a string of 11 bytes represents 88 bits.
>> How do you use something else that is that compact?
>
> VB strings are not strings of bytes, they're BSTR -- strings of Unicode
> characters, which are 16 bits. Externally they may appear to be 8 bits but
> the transform is subject to distortion in certain ranges, which is why
> Thorsten cautioned about Chr$(). Plus, each string has a 32-bit size prefix,
> so your 88 bits becomes 208 bits of storage.
>
> Using long integers would give you (up to) 32 bits of data for each 32 bits
> of storage, and would not be subject to Unicode distortion.
>
> If you use arrays there will be additional storage overhead (the SAFEARRAY
> structure). Larger arrays minimize that impact. Whatever logic you're using
> to compute the character position within the string would work as well for
> long integer (or even byte) arrays, and should be much much faster than
> strings.

Wrong. They can be and are strings made of Bytes (or whatever you want
to call it). I have created them and disassembled them. No, 88 is
still 88 and I have code to prove that.

Give it a try.

Dim sStr as String
sStr = ChrB$(1) & ChrB$(2) & ChrB$(3)
' then do a
Debug.Print LenB(sStr)

' then
Dim aByte() as Byte
aByte = sStr
Debug.Print LBound(aByte), UBound(aByte)

Surprise.
etc.

And if anybody read what I have been working on they would remember:
1) I have only strings to work with. why would I want to create and
maintain a parallel array of anything else?
2) If nothing is selected the the string containing the BitField is =
"" taking up very little room indeed (just the usual String overhead)
but can be expanded to whatever BitField is needed without regard to
the limitations of Long (32 bits) etc. e.g. 253 (randomly chosen number
for illustrative purposes only)
3) In my case the most common situation is that the BitField having
contents is used on a small portion of the full array of strings which
comprise a Row,Column matrix.

Also, since this is a user interaction (mostly), the time to work the
Bit String stuff being measured at around 10uSec (10 microseconds) on
my old laptop seems fast enough to me. I doubt the user will notice
any difference between 10uSec and 1uSec. and when it is not a user
only operation, then it is a file copy or some other relatively long
interaction with the file system and is a very teeny tiny small
(technical term) percentage of what is happening.

This is just so much fun!


Thorsten Albers

10/24/2011 12:48:00 AM

0

BeeJ <nospam@spamnot.com> schrieb im Beitrag
<j8202n$p2$1@speranza.aioe.org>...
> Yeah, so how would you implement that?
> ...
> Show me some examples of your way.

I did so already in a previous posting of mine.

--
Thorsten Albers

gudea at gmx.de

Thorsten Albers

10/24/2011 12:48:00 AM

0

BeeJ <nospam@spamnot.com> schrieb im Beitrag
<j829k3$mqc$1@speranza.aioe.org>...
> Wrong. They can be and are strings made of Bytes (or whatever you want
> to call it). I have created them and disassembled them. No, 88 is
> still 88 and I have code to prove that.
>
> Give it a try.
>
> Dim sStr as String
> sStr = ChrB$(1) & ChrB$(2) & ChrB$(3)
> ' then do a
> Debug.Print LenB(sStr)

What exactly is happening here:
- 1 is packed in the low byte of character 1
- 2 is packed in the high byte of character 1
- 3 is packed in the low byte of character 2
- the high byte of character 2 is set to 0
- the BSTR length descriptor is set to 3 although actually there are 4
characters

There will be no problem with this method as long as you use only AscB() to
read the contents of a byte of the string (as well as MidB$() to address
the bytes and LenB() to get the count of bytes).

But there is useless overhead:

a)

Creation
- ChrB$(3) -> memory allocation for a 4 byte string pointer and a 4 + 2 + 2
byte string
- ChrB$(2) -> memory allocation for a 4 byte string pointer and a 4 + 2 + 2
byte string
- ChrB$(2) & ChrB$(3) -> memory allocation for a 4 byte string pointer and
a 4 + 2 + 2 + 2 byte string
(= temp. string)
- ChrB$(1) -> memory allocation for a 4 byte string pointer and a 4 + 2 + 2
byte string
- ChrB$(1) & <temp. string> -> memory allocation for a 4 byte string
pointer and a 4 + 2 + 2 + 2 + 2 byte string

Access
If AscB(MidB$(sStr, 1)) And &H1 Then
- Build the address of the string character
- MidB$() -> allocate memory for a 4 byte string pointer and a 4 + 2 + 2
byte string
- Read the integer value
- Bitwise combine the two values

<>

b)

Creation
Dim abBytes(0 To 2) As Byte
abByte(0) = 1
abByte(1) = 2
abByte(2) = 3
- Dim ... -> memory allocation for 3 + 1 bytes

Access
If abByte(0) And &H1 Then
- Build the address of the array item
- Bitwise combine the two values

- a) needs less bytes of memory (4 + 4 + 2 + 2 + 2 + 2 = 16 bytes) then b)
(24 + 3 + 1 = 28 bytes)
- b) needs less CPU time then a)

> 1) I have only strings to work with. why would I want to create and
> maintain a parallel array of anything else?

Because of performance. String memory allocation in VB is done via the OLE
library and anything else but fast.

> 2) If nothing is selected the the string containing the BitField is =
> "" taking up very little room indeed (just the usual String overhead)
> but can be expanded to whatever BitField is needed without regard to
> the limitations of Long (32 bits) etc. e.g. 253 (randomly chosen number
> for illustrative purposes only)

There is no difference with e.g. a byte array since Erase and ReDim is
available, i.e. the array can be expanded and cleared like a string can.

--
Thorsten Albers

gudea at gmx.de