Effectively storing bit indexes - c#

I want to store certain indexes in a sequence of bits. The number of bits are powers of
two and it is safe to assume that maximum index to be 255 (starting index is 0). Earlier i was storing every index as an integer. But that occupies too much of memory.
I want to use something like masks.
ex: If i want to store the indexes 0,3,5 then i store 101001 i.e. 41 as an integer.
The problem is that maximum index that i have is 255 and using above technique i can store indexes
only till 64(using 64 bit integer). Is there any other way i can do this??
Thanks :-)

.NET has a built-in class for this kind of thing: BitArray
This will let you store a string of bits (in the form of bools) efficiently.
You can perform bitwise operations on BitArrays with the And, Or, Xor, and Not methods.
You can initialize a BitArray with bools, bytes, or ints. For example, you can initialize it with 00101100 like this:
BitArray bits = new BitArray(new byte[] { 0x2C }); // 0x2C == 00101100

You can use 2 bit indexes for every bit index.
Pratically with 10 bits (index from 1 to 10, set bits 0, 4, 8):
Single index:
i = 0100010001
Index1 = i
Two combined indexes:
i1 = 01000
i2 = 10001
Index2 = [i1, i2];
Index2.fragment_length = 5
Array
In pseudocode, to retrieve or set a bit
set(Index, bit) {
fragment = quotient(bit, Index.flagment_length); //quotient = integer division
bit_index = module(bit, Index.flagment_length); //index of the bit in the fragment
set(Index[fragment], bit-or(Index[Fragment], bit-shift-left(1 << bit_index))); //Set the bit indexes vector fragment with or-ing the appropriate bitmask
}
get(Index, bit) {
fragment = quotient(bit, Index.flagment_length); //quotient = integer division
bit_index = module(bit, Index.flagment_length); //index of the bit in the fragment
if (get(Index[fragment], bit-and(Index[Fragment], bit-shift-left(1 << bit_index))) > 0) then true else false; //Get the bit indexes vector fragment bit with and-ing the appropriate bitmask and return true or false
}
I hope to have understood your requirements!

In java the bit indexing made easy as the following little tutorial...
This class implements a vector of bits that grows as needed. Each component of the bit set has a boolean value. The bits of a BitSet are indexed by nonnegative integers. Individual indexed bits can be examined, set, or cleared. One BitSet may be used to modify the contents of another BitSet through logical AND, logical inclusive OR, and logical exclusive OR operations.
By default, all bits in the set initially have the value false.
Every bit set has a current size, which is the number of bits of space currently in use by the bit set. Note that the size is related to the implementation of a bit set, so it may change with implementation. The length of a bit set relates to logical length of a bit set and is defined independently of implementation.
Unless otherwise noted, passing a null parameter to any of the methods in a BitSet will result in a NullPointerException. A BitSet is not safe for multithreaded use without external synchronization.

Related

Set last 4 bits to 0

I want to set the last 4 bits of my byte list to 0. I've tried this line of code but it does not work:
myData = 1111.1111
myData should be = 1111.0000
(myData & 0x0F) >> 4
Assuming you mean that "4 last bits" is 4 least significant bits, I have this code example for you:
var myData = 0xFF;
var result = myData & ~0xF;
So, basically, what you want here is not to set the 4 least significant bits to 0, but to preserve the rest of the data. To achieve this you have to prepare the "passthrough" mask, which matches the criteria, this is the one's complement of the non-needed bits mask i.e. the one's complement of the 0xF (also note that 0xF = (2 to the power of 4) - 1 -- where 4 is the number of the desired cleared out LSBs). Thus, ~0xF is the desired mask -- you just have to apply it to the number -- myData & ~0xF.
N.B. The one's complement approach is better than magical numbers, pre-computed yourself (such as 0xF in the anwser above), as the compiler will generate the valid number of MSBs (most significant bits) for the type you use this approach against.
An even safer approach would be to compute the one's complement of the variable itself, giving the effective code stated below:
var myData = 0xFF;
var result = ~(~myData | 0xF);
That's it!
To preserve the 4 high bits and zero the 4 low bits
myData & 0xF0

Mapping two integers to one (with an upperbound)

I'm looking for a function that maps two (positive) integers into a single new integer, which can be reversed to the original combination.
The question has been asked before, for example Mapping two integers to one, in a unique and deterministic way. The difference is that one of the integers is bound to an upper bound which is quite small, for example 50. The other integer is unbound.
What i'm trying to solve is that I have and 1-50 arrays with numbers 1 - max int (but mostly < 10.000.000).
array1 {1,2,3,4,5,6,7..N)
array2 {1,2,3,4,5,6,7..N)
array50 {1,2,3,4,5,6,7..N)
Now I want to create a single new array which combines these N arrays to a single new array, where each number is reversable to the original array. So I thought about creating pairs, one number pointing to the array and one to the actual number in the array.
If I use the default functions like Cantor Pairing Function I get huge numbers very fast, and i'm trying to keep those numbers as small as possible.
It would be preferably if the biggest part would just fit in a Int32 instead of a long. I think it should be possible because one of the numbers in my pair is bounded by 50, but I can't figure out how.
If you have two numbers
a from 0 to a_max - 1
b from 0 to 232/a_max - 1
you can combine them as
x = a + a_max*b;
and the combined number x will fit into a 32 bit unsigned integer.
To decode them, use
a = x%a_max;
b = x/a_max;
It is not possible to find a more efficient packing, because every possible output value is used. (There are no 'gaps' in the output.) If the bounds for b are too narrow, a larger output type must be used.

C#: Left Rotation Algorithm for different Bit Numbering Schemes

So I have the following RotateLeft algorithm in C#:
public static ushort RotateLeft(ushort value, int count)
{
int left = value << count;
int right = value >> (16 - count);
return (ushort)(left | right);
}
Does this algorithm differ if the numbering scheme is different?
By numbering scheme I mean if it's MSB-0 or LSB-0
MSB-0
0 7
1 0 0 1 0 1 1 0
LSB-0
7 0
1 0 0 1 0 1 1 0
Say I wanted to shift left by 1, does having a different numbering scheme affect the algorithm?
It looks like that algorithm is agnostic of the underlying system's little- or big- endianness. That is to say, it will work the same regardless of the numbering scheme, since the OR operation adds the shifted bits back in on the other side before returning. Assuming you're using it for bit-level operations and flag checks, this might be all you need.
Without knowing how it fits into the rest of your program it's hard to say whether it will work the way you expect across different platforms using opposite bit numbering schemes. For example, if you run this on a device using MSB-0 and write some shifted data to a binary file, then read that binary data back in on a device using LSB-0, it probably won't be what you're expecting.
If your goal is to have your software work the same across differently-endian systems, take a look at the .NET BitConverter Class. If you're using this for efficient mathematical operations, the static BitConverter.IsLittleEndian field will let you check the underlying architecture so that you can shift the other way or reverse binary data accordingly.

Read/Write compressed binary data

I read all over the place people talk about compressing objects on a bit by bit scale. Things like "The first three bits represent such and such, then the next two represent this and twelve bits for that"
I understand why it would be desirable to minimize memory usage, but I cannot think of a good way to implement this. I know I would pack it into one or more integers (or longs, whatever), but I cannot envision an easy way to work with it. It would be pretty cool if there were a class where I could get/set arbitrary bits from an arbitrary length binary field, and it would take care of things for me, and I wouldn't have to go mucking about with &'s and |'s and masks and such.
Is there a standard pattern for this kind of thing?
From MSDN:
BitArray Class
Manages a compact array of bit values, which are represented as Booleans, where true indicates that the bit is on (1) and false indicates the bit is off (0).
Example:
BitArray myBitArray = new BitArray(5);
myBitArray[3] = true; // set bit at offset 3 to 1
BitArray allows you to set only individual bits, though. If you want to encode values with more bits, there's probably no way around mucking about with &'s and |'s and masks and stuff :-)
You might want to check out the BitVector32 structure in the .NET Framework. It lets you define "sections" which are ranges of bits within an int, then read and write values to those sections.
The main limitation is that it's limited to a single 32-bit integer; this may or may not be a problem depending on what you're trying to do. As dtb mentioned, BitArray can handle bit fields of any size, but you can only get and set a single bit at a time--there is no support for sections as in BitVector32.
What you're looking for are called bitwise operations.
For example, let's say we're going to represent an RGB value in the least significant 24 bits of an integer, with R being bits 23-16, G being bits 15-8, and B being bits 7-0.
You can set R to any value between 0 and 255 without effecting the other bits like this:
void setR(ref int RGBValue, int newR)
{
int newRValue = newR << 16; // shift it left 16 bits so that the 8 low-bits are now in position 23-16
RGBValue = RGBValue & 0x00FF; // AND it with 0x00FF so that the top 16 bits are set to zero
RGBValue = RGBValue | newRValue; // now OR it with the newR value so that the new value is set.
}
By using bitwise ANDs and ORs (and occasionally more exotic operations) you can easily set and clear any individual bit of a larger value.
Rather than using toolkit or platform specific wrapper classes I think you are better off biting the bullet and learning your &s and |s and 0x04s and how all the bitwise operators work. By and large that's how its done for most projects, and the operations are extremely fast. The operations are pretty much identical on most languages so you won't be stuck dependant on some specific toolkit.

(C#) Is there a way to set the value of a single bit through pointers?

What I mean is: Imagine we have a 8 byte variable that has a high value and low value. I can make one pointer point to the upper 4 bytes and other point to the lower 4 bytes, and set/retrieve their values without problems. Now, is there a way to get/set values for anything smaller than a byte? If instead of dividing it in two 4 bytes "variables", I'd want to consider eight 1 byte variables I could use a bool, but there is no defined smaller variable in c#. Would it possible to divide it to 16 just with pointers? Or even in 32, 64? It wouldn't right?
This is a pretty academic question, I know this can be achieved otherwise with bitshiffting, unions(Struct.Explicit), etc. Thanks!
No, C# does not support bit fields and a byte is the minimum amount of addressable memory. You can manually provide properties that change one or several specific bits but you have to provide packing/unpacking logic yourself:
public bool Bit5 {
get { return (field & 32) != 0; }
set { if (value) field |= 32; else field &= ~32; }
}
By the way, I don't know how you achieve it using LayoutKind.Explicit as the minimum FieldOffset you can specify is one byte.
As a side note, even C++ that can do this with bit fields will just hide the bitwise tricks and makes the compiler do it instead of you. There's no way you could grab something less than a byte from memory to a register, at least on x86 architecture.

Categories

Resources