Reputation: 897
I would like to know how I can read and write specific bits efficiently to a ushort integer.
The methods would be something like so:
// Sets the bit positioned at bitNumber in the ushort integer b
// to be either 1 or 0 depending on state.
public ushort SetBit(ushort b, int bitNumber, bool state)
{
ushort result = b;
// Code to set the specific bit in ushort result.
return result
}
// Returns the value of the bit in position bitNumber from the
// ushort b as a true or false.
public bool GetBit(ushort b, int bitNumber)
{
bool stateOfBit = false;
// Code to read the bit into stateOfBit.
return stateOfBit;
}
I have tried using BitArray class but it only takes a byte or a 32 bit integer.
Does someone know how to do this?
Thanks
Upvotes: 1
Views: 1693
Reputation: 21
I really liked juharr's answer (it looks cleaner and has less variable creation), but it is not right. The last check should be (> 0
) not (> 1
).
public static ushort SetBit(ushort b, int bitNumber, bool state)
{
if(bitNumber < 1 || bitNumber > 16)
throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");
return state ?
(ushort)(b | (1 << (bitNumber - 1))) :
(ushort)(b & ~(1 << (bitNumber - 1)));
}
public static bool GetBit(ushort b, int bitNumber)
{
if (bitNumber < 1 || bitNumber > 16)
throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");
return (b & (1 << (bitNumber - 1))) > 0;
}
Upvotes: 0
Reputation: 32266
First you need to guard against invalid bitNumber
values by making sure it is between 1 and 16.
Then for setting you either want to "OR" it with a mask that has that bit set to one (by left shifting 1 to the desired position) if state
is true. Otherwise you "AND" it with a mask where all the bits are 1 except the one you want to set to zero (accomplished by NOT-ing the other mask).
For determining if the bit is set just "AND" it to the first mask mentioned and compare to zero.
public static ushort SetBit(ushort b, int bitNumber, bool state)
{
if(bitNumber < 1 || bitNumber > 16)
throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");
return state ?
(ushort)(b | (1 << (bitNumber - 1))) :
(ushort)(b & ~(1 << (bitNumber - 1)));
}
public static bool GetBit(ushort b, int bitNumber)
{
if (bitNumber < 1 || bitNumber > 16)
throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");
return (b & (1 << (bitNumber - 1))) > 1;
}
This assumes that you want bitNumber
to be one-based from the least significant bit, or right most bit. If you want zero-based just remove the - 1
used after bitNumber
in all the code and adjust the if
statement accordingly. To make this start from the most significant or left most bit then just subtract 16 from bitNumber
instead of 1 for one-based, or subtract 15 for zero-based.
Upvotes: 3
Reputation: 8894
ushort s = 0;
//set the 5th bit from the right to true
s |= 1 << 5;
//set the 5th bit from the right to false
//~ will return a negative number, so casting to int is necessary
int i = s;
i &= ~(1 << 5);
s = (ushort)i;
To do this in a method, you can either have the method return it or pass the ushort by reference:
public void SetBit(ref ushort b, int bitNumber, bool state) {
if (bitNumber < 0 || bitNumber > 15)
//throw an Exception or return
if (state) {
b |= (ushort)(1 << bitNumber);
} else {
int i = b;
i &= ~(1 << bitNumber);
b = (ushort)i;
}
}
public bool GetBit(ushort b, int bitNumber) {
if (bitNumber < 0 || bitNumber > 15)
//throw an Exception or just return false
return (b & (1 << bitNumber)) > 0;
}
To count bitNumber from the left, you need 15 - bitNumber
Upvotes: 2