I need an efficient method with the following signature:
public byte SetBits(byte oldValue, byte newValue, int startBit, int bitCount)
Which returns oldValue, only that starting from its startbit bit up to its startbit + bitcount bit (zero-based), it's replaced with the first bitcount bits of newValue
For example, if:
oldValue = 11101101
newValue = 10000011
startBit = 1
bitCount = 2
Then the result would be: 11101111 (the segment 10 in oldValue is replaced with the corresponding 11 segment in newValue)
Here you go... Bitshift both directions to get the mask... then use it to generate the new byte
public static byte SetBits(byte oldValue, byte newValue, int startBit, int bitCount)
{
if (startBit < 0 || startBit > 7 || bitCount < 0 || bitCount > 7
|| startBit + bitCount > 8)
throw new OverflowException();
int mask = (255 >> 8 - bitCount) << startBit;
return Convert.ToByte((oldValue & (~mask)) | ((newValue << startBit) & mask));
}
startBit--; //account for 0 indexing
byte flag = 1 << startBit;
for (int i = startBit; i < bitCount; i++, flag <<= 1)
{
byte mask = newValue & flag;
if (mask != 0)
oldValue |= mask;
else
oldValue &= ~(flag);
}
return oldValue;
Some brain compiled code here but it should be along the lines that you want if I read the question correctly.
If I understood your question, I think this is what you are after:
byte mask = 0xFF;
for (int i = startPos-1; i < numBits; i++)
{
if ((newValue & (1 << i)) == 1)
{
mask = (byte)(mask | (1 << i));
}
else
{
mask = (byte)(mask &~(1<<i));
}
}
return (byte)(oldValue & mask);
This code is based on some neat tricks from Low Level Bit Hacks You Absolutely Must Know
I know setting a bit in a byte initialized to 0xFF is really a no-op, but I felt the code should be left in as it can help show off what is really going on. I encourage users of the code to optimize it as needed.
Related
I have an array of ushorts and want to iterate over the array and check if the first two bits of that ushort are 11 if so I want to clear them. However the bit mask I am using to read the first two bits in my conditional are not working properly and the if statement does not trigger when the first two bits are 11
static public void trimData(ushort[] rawData)
{
for(int i = 0; i < rawData.Length; i++)
{
if (((ushort)(rawData[i] & (1 << 15)) == 1) && ((ushort)(rawData[i] & (1 << 14)) == 1))
{
rawData[i] = (ushort)(rawData[i]&~(1<<15));
rawData[i] = (ushort)(rawData[i]&~(1<<14));
}
}
}
How can I use bitmasks to do this correctly?
You can shift these bits to have them being the rightmost ones and then mask with 0b11:
// drop all bits except topmost ones 16 - 14 == 2 which are now the rightmost
int bits = (rawData[i] >> 14) & 0b11;
if (bits == 0b11) {
// Both bits are set
}
To clear these bits you use XOR ^ (since 1 ^ 1 == 0):
int mask = 0b11 << 14;
// remove 14th and 15th set bits
rawData[i] = (ushort)(rawData[i] ^ mask);
Let's combine these parts:
if (((rawData[i] >> 14) & 0b11) == 0b11)
rawData[i] = (ushort)(rawData[i] ^ (0b11 << 14));
Finally, the method can be
public static void trimData(ushort[] rawData) {
if (rawData is null)
throw new ArgumentNullException(nameof(rawData));
for (int i = 0; i < rawData.Length; i++)
if (((rawData[i] >> 14) & 0b11) == 0b11)
rawData[i] = (ushort)(rawData[i] ^ (0b11 << 14));
}
Can you try this?
static public void trimData(ushort[] rawData)
{
for(int i = 0; i < rawData.Length; i++)
{
if (49152 == (49152 & rawData[i]))
{
rawData = rawData.Where(x=>x != rawData[i]).ToArray();
}
}
}
49152 = (2^14) + (2^15)
For example, if it is 0xc0, then the result is 0x40,
Since 0xc0 is equal to binary 11000000, the result should be 01000000.
public static byte Puzzle(byte x) {
byte result = 0;
byte[] masks = new byte[]{1,2,4,8,16,32,64,128};
foreach(var mask in masks)
{
if((x&mask)!=0)
{
return mask;
}
}
return 0;
}
This is my current solution. It turns out this question can be solved in 3-4 lines...
public static byte Puzzle(byte x) {
return (byte) (x & (~x ^ -x));
}
if x is bbbb1000, ~x is BBBB0111 (B is !b)
-x is really ~x+1, (2's complement) so adding 1 to BBBB0111 is BBBB1000
~x ^ -x then is 00001111 & with x gives the lowest 1 bit.
A better answer was supplied by harold in the comments
public static byte Puzzle(byte x) {
return (byte) (x & -x);
}
Maby not the best solution, but you can prepare an array byte[256], store the result for each number and then use it.
Another solution in 1 line:
return (byte)((~(x | (x << 1) | (x << 2) | (x << 3) | (x << 4) | (x << 5) | (x << 6) | (x << 7) | (x << 8)) + 1) >> 1);
Hardly a 1-line solution, but at least it doesn't use the hardcoded list of the bits.
I'd do it with some simple bit shifting. Basically, down-shifting the value until the lowest bit is not 0, and then upshifting 1 with the amount of performed shifts to reconstruct the least significant value. Since it's a 'while' it needs an advance zero check though, or it'll go into an infinite loop on zero.
public static Byte Puzzle(Byte x)
{
if (x == 0)
return 0;
byte shifts = 0;
while ((x & 1) == 0)
{
shifts++;
x = (Byte)(x >> 1);
}
return (Byte)(1 << shifts);
}
Can this function be improved upon to make it more efficient?:
private unsafe uint GetValue(uint value, int bitsToGrab, int bitsToMoveOver)
{
byte[] bytes = BitConverter.GetBytes(value);
uint myBitMask = 0x80; //MSB of 8 bits (byte)
int arrayIndex = 0;
for (int i = 0; i < bitsToMoveOver; i++)
{
if (myBitMask == 0)
{
arrayIndex++;
myBitMask = 0x80;
}
myBitMask >>= 1;
}
uint outputMask1 = (uint)(1 << (bitsToGrab - 1));
uint returnVal = 0;
for (int i = 0; i < bitsToGrab; i++)
{
if (myBitMask == 0)
{
arrayIndex++;
myBitMask = 0x80;
}
if ((bytes[arrayIndex] & myBitMask) > 0)
{
returnVal |= outputMask1;
}
outputMask1 >>= 1;
myBitMask >>= 1;
}
return returnVal;
}
i have an array of uints. each uint contains multiple pieces of data. In order to get the information, i pass in the number of bits, and the offset of those bits. Using that information, i build an output value.
The offset is generally on a byte boundary, but i cannot guarantee that it will be.
I'm actually really looking to see if i can simplify the code. Am i unnecessarily verbose in the code, or could it be done a bit cleaner?
Updated function: How do you guys feel about this?
private unsafe uint GetValue(uint value, int bitsToGrab, int bitsToMoveOver)
{
if (bitsToGrab + bitsToMoveOver >= 32)
{
return 0;
}
byte[] bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes);
uint newValue = BitConverter.ToUInt32(bytes, 0);
uint grabMask = (0xFFFFFFFF << (32 - bitsToGrab));
grabMask >>= bitsToMoveOver;
uint returnVal = (newValue & grabMask) >> (32 - bitsToMoveOver - bitsToGrab);
return returnVal;
}
This needs testing (and assumes that bitsToGrab + bitsToMoveOver <= 32), but I think you can do this:
uint grabMask = ~(0xFFFFFFFF << (bitsToGrab + bitsToMoveOver));
return (value & grabMask) >> bitsToMoveOver;
Since the OP has indicated that it should be sampling bits from an internal binary representation of the number (including endian encoding), with byte order swapping within each word, you can swap bytes first like this:
uint reorderedValue = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0x00FF00FF);
uint grabMask = ~(0xFFFFFFFF << (bitsToGrab + bitsToMoveOver));
return (reorderedValue & grabMask) >> bitsToMoveOver;
I have two bytes. I need to turn them into two integers where the first 12 bits make one int and the last 4 make the other. I figure i can && the 2nd byte with 0x0f to get the 4 bits, but I'm not sure how to make that into a byte with the correct sign.
update:
just to clarify I have 2 bytes
byte1 = 0xab
byte2 = 0xcd
and I need to do something like this with it
var value = 0xabc * 10 ^ 0xd;
sorry for the confusion.
thanks for all of the help.
int a = 10;
int a1 = a&0x000F;
int a2 = a&0xFFF0;
try to use this code
For kicks:
public static partial class Levitate
{
public static Tuple<int, int> UnPack(this int value)
{
uint sign = (uint)value & 0x80000000;
int small = ((int)sign >> 28) | (value & 0x0F);
int big = value & 0xFFF0;
return new Tuple<int, int>(small, big);
}
}
int a = 10;
a.UnPack();
Ok, let's try this again knowing what we're shooting for. I tried the following out in VS2008 and it seems to work fine, that is, both outOne and outTwo = -1 at the end. Is that what you're looking for?
byte b1 = 0xff;
byte b2 = 0xff;
ushort total = (ushort)((b1 << 8) + b2);
short outOne = (short)((short)(total & 0xFFF0) >> 4);
sbyte outTwo = (sbyte)((sbyte)((total & 0xF) << 4) >> 4);
Assuming you have the following to bytes:
byte a = 0xab;
byte b = 0xcd;
and consider 0xab the first 8 bits and 0xcd the second 8 bits, or 0xabc the first 12 bits and 0xd the last four bits. Then you can get the these bits as follows;
int x = (a << 4) | (b >> 4); // x == 0x0abc
int y = b & 0x0f; // y == 0x000d
edited to take into account clarification of "signing" rules:
public void unpack( byte[] octets , out int hiNibbles , out int loNibble )
{
if ( octets == null ) throw new ArgumentNullException("octets");
if ( octets.Length != 2 ) throw new ArgumentException("octets") ;
int value = (int) BitConverter.ToInt16( octets , 0 ) ;
// since the value is signed, right shifts sign-extend
hiNibbles = value >> 4 ;
loNibble = ( value << 28 ) >> 28 ;
return ;
}
Hello quick question regarding bit shifting
I have a value in HEX: new byte[] { 0x56, 0xAF };
which is 0101 0110 1010 1111
I want to the first N bits, for example 12.
Then I must right-shift off the lowest 4 bits (16 - 12) to get 0000 0101 0110 1010 (1386 dec).
I can't wrap my head around it and make it scalable for n bits.
Sometime ago i coded these two functions, the first one shifts an byte[] a specified amount of bits to the left, the second does the same to the right:
Left Shift:
public byte[] ShiftLeft(byte[] value, int bitcount)
{
byte[] temp = new byte[value.Length];
if (bitcount >= 8)
{
Array.Copy(value, bitcount / 8, temp, 0, temp.Length - (bitcount / 8));
}
else
{
Array.Copy(value, temp, temp.Length);
}
if (bitcount % 8 != 0)
{
for (int i = 0; i < temp.Length; i++)
{
temp[i] <<= bitcount % 8;
if (i < temp.Length - 1)
{
temp[i] |= (byte)(temp[i + 1] >> 8 - bitcount % 8);
}
}
}
return temp;
}
Right Shift:
public byte[] ShiftRight(byte[] value, int bitcount)
{
byte[] temp = new byte[value.Length];
if (bitcount >= 8)
{
Array.Copy(value, 0, temp, bitcount / 8, temp.Length - (bitcount / 8));
}
else
{
Array.Copy(value, temp, temp.Length);
}
if (bitcount % 8 != 0)
{
for (int i = temp.Length - 1; i >= 0; i--)
{
temp[i] >>= bitcount % 8;
if (i > 0)
{
temp[i] |= (byte)(temp[i - 1] << 8 - bitcount % 8);
}
}
}
return temp;
}
If you need further explanation please comment on this, i will then edit my post for clarification...
You can use a BitArray and then easily copy each bit to the right, starting from the right.
http://msdn.microsoft.com/en-us/library/system.collections.bitarray_methods.aspx
you want something like...
var HEX = new byte[] {0x56, 0xAF};
var bits = new BitArray(HEX);
int bitstoShiftRight = 4;
for (int i = 0; i < bits.Length; i++)
{
bits[i] = i < (bits.Length - bitstoShiftRight) ? bits[i + bitstoShiftRight] : false;
}
bits.CopyTo(HEX, 0);
If you have k total bits, and you want the "first" (as in most significant) n bits, you can simply right shift k-n times. The last k-n bits will be removed, by sort of "falling" off the end, and the first n will be moved to the least significant side.
Answering using C-like notation, assuming bits_in_byte is the number of bits in a byte determined elsewhere:
int remove_bits_count= HEX.count*bits_in_byte - bits_to_keep;
int remove_bits_in_byte_count= remove_bits_count % bits_in_byte;
if (remove_bits_count > 0)
{
for (int iteration= 0; iteration<min(HEX.count, (bits_to_keep + bits_in_byte - 1)/bits_in_byte); ++iteration)
{
int write_index= HEX.count - iteration - 1;
int read_index_lo= write_index - remove_bits_count/bits_in_byte;
if (read_index_lo>=0)
{
int read_index_hi= read_index_lo - (remove_bits_count + bits_in_byte - 1)/bits_in_byte;
HEX[write_index]=
(HEX[read_index_lo] >> remove_bits_in_byte_count) |
(HEX[read_index_hi] << (bits_in_byte - remove_bits_in_byte_count));
}
else
{
HEX[write_index]= 0;
}
}
}
Assuming you are overwriting the original array, you basically take every byte you write to and figure out the bytes that it would get its shifted bits from. You go from the end of the array to the front to ensure you never overwrite data you will need to read.