In order to utilize a byte to its fullest potential, I'm attempting to store two unique values into a byte: one in the first four bits and another in the second four bits. However, I've found that, while this practice allows for optimized memory allocation, it makes changing the individual values stored in the byte difficult.
In my code, I want to change the first set of four bits in a byte while maintaining the value of the second four bits in the same byte. While bitwise operations allow me to easily retrieve and manipulate the first four bit values, I'm finding it difficult to concatenate this new value with the second set of four bits in a byte. The question is, how can I erase the first four bits from a byte (or, more accurately, set them all the zero) and add the new set of 4 bits to replace the four bits that were just erased, thus preserving the last 4 bits in a byte while changing the first four?
Here's an example:
// Changes the first four bits in a byte to the parameter value
public void changeFirstFourBits(byte newFirstFour)
{
// If 'newFirstFour' is 0101 in binary, make 'value' 01011111 in binary, changing
// the first four bits but leaving the second four alone.
}
private byte value = 255; // binary: 11111111
Use bitwise AND (&) to clear out the old bits, shift the new bits to the correct position and bitwise OR (|) them together:
value = (value & 0xF) | (newFirstFour << 4);
Here's what happens:
value : abcdefgh
newFirstFour : 0000xyzw
0xF : 00001111
value & 0xF : 0000efgh
newFirstFour << 4 : xyzw0000
(value & 0xF) | (newFirstFour << 4) : xyzwefgh
When I have to do bit-twiddling like this, I make a readonly struct to do it for me. A four-bit integer is called nybble, of course:
struct TwoNybbles
{
private readonly byte b;
public byte High { get { return (byte)(b >> 4); } }
public byte Low { get { return (byte)(b & 0x0F); } {
public TwoNybbles(byte high, byte low)
{
this.b = (byte)((high << 4) | (low & 0x0F));
}
And then add implicit conversions between TwoNybbles and byte. Now you can just treat any byte as having a High and Low byte without putting all that ugly bit twiddling in your mainline code.
You first mask out you the high four bytes using value & 0xF. Then you shift the new bits to the high four bits using newFirstFour << 4 and finally you combine them together using binary or.
public void changeHighFourBits(byte newHighFour)
{
value=(byte)( (value & 0x0F) | (newFirstFour << 4));
}
public void changeLowFourBits(byte newLowFour)
{
value=(byte)( (value & 0xF0) | newLowFour);
}
I'm not really sure what your method there is supposed to do, but here are some methods for you:
void setHigh(ref byte b, byte val) {
b = (b & 0xf) | (val << 4);
}
byte high(byte b) {
return (b & 0xf0) >> 4;
}
void setLow(ref byte b, byte val) {
b = (b & 0xf0) | val;
}
byte low(byte b) {
return b & 0xf;
}
Should be self-explanatory.
public int SplatBit(int Reg, int Val, int ValLen, int Pos)
{
int mask = ((1 << ValLen) - 1) << Pos;
int newv = Val << Pos;
int res = (Reg & ~mask) | newv;
return res;
}
Example:
Reg = 135
Val = 9 (ValLen = 4, because 9 = 1001)
Pos = 2
135 = 10000111
9 = 1001
9 << Pos = 100100
Result = 10100111
A quick look would indicate that a bitwise and can be achieved using the & operator. So to remove the first four bytes you should be able to do:
byte value1=255; //11111111
byte value2=15; //00001111
return value1&value2;
Assuming newVal contains the value you want to store in origVal.
Do this for the 4 least significant bits:
byte origVal = ???;
byte newVal = ???
orig = (origVal & 0xF0) + newVal;
and this for the 4 most significant bits:
byte origVal = ???;
byte newVal = ???
orig = (origVal & 0xF) + (newVal << 4);
I know you asked specifically about clearing out the first four bits, which has been answered several times, but I wanted to point out that if you have two values <= decimal 15, you can combine them into 8 bits simply with this:
public int setBits(int upperFour, int lowerFour)
{
return upperFour << 4 | lowerFour;
}
The result will be xxxxyyyy where
xxxx = upperFour
yyyy = lowerFour
And that is what you seem to be trying to do.
Here's some code, but I think the earlier answers will do it for you. This is just to show some sort of test code to copy and past into a simple console project (the WriteBits method by be of help):
static void Main(string[] args)
{
int b1 = 255;
WriteBits(b1);
int b2 = b1 >> 4;
WriteBits(b2);
int b3 = b1 & ~0xF ;
WriteBits(b3);
// Store 5 in first nibble
int b4 = 5 << 4;
WriteBits(b4);
// Store 8 in second nibble
int b5 = 8;
WriteBits(b5);
// Store 5 and 8 in first and second nibbles
int b6 = 0;
b6 |= (5 << 4) + 8;
WriteBits(b6);
// Store 2 and 4
int b7 = 0;
b7 = StoreFirstNibble(2, b7);
b7 = StoreSecondNibble(4, b7);
WriteBits(b7);
// Read First Nibble
int first = ReadFirstNibble(b7);
WriteBits(first);
// Read Second Nibble
int second = ReadSecondNibble(b7);
WriteBits(second);
}
static int ReadFirstNibble(int storage)
{
return storage >> 4;
}
static int ReadSecondNibble(int storage)
{
return storage &= 0xF;
}
static int StoreFirstNibble(int val, int storage)
{
return storage |= (val << 4);
}
static int StoreSecondNibble(int val, int storage)
{
return storage |= val;
}
static void WriteBits(int b)
{
Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(b),0));
}
}
Related
Can we access randomly a part of byte.I mean can i access three bits of a bit randomnly without using BitArray and accessing by byte.
Is there any possibility of accessing bit from byte and if not why it is not possible to access it and is it depends on any criteria
You can use the Bitwise And (&) operator in order to read a specific bit from a byte. I'll give some examples by using the 0b prefix, which in C# allows you to write binary literals in your code.
So suppose you have the following byte value:
byte val = 0b10010100; // val = 148 (in decimal)
byte testBits = 0b00000100; // set ONLY the BITS you want to test here...
if ( val & testBits != 0 ) // bitwise and will return 0 if the bit is NOT SET.
Console.WriteLine("The bit is set!");
else
Console.WriteLine("The bit is not set....");
Here's a method for you to test any bit in a given byte, which uses the Left-Shift operator applied to the number 1 in order to generate a binary number which is able to be used for testing against any arbitrary bit in the given byte:
public static int readBit(byte val, int bitPos)
{
if ((val & (1 << bitPos)) != 0)
return 1;
return 0;
}
You can use this method to print which bits are set in a given byte:
byte val = 0b10010100;
for (int i = 0; i < 8; i++)
{
int bitValue = readBit(val, i);
Console.WriteLine($"Bit {i} = {bitValue}");
}
The output from the code above should be:
Bit 0 = 0
Bit 1 = 0
Bit 2 = 1
Bit 3 = 0
Bit 4 = 1
Bit 5 = 0
Bit 6 = 0
Bit 7 = 1
you can use bit shifting
var bitNumber = 0;
var firstBit = (b & (1 << bitNumber)) != 0 ;
we can convert this to extension method
public static class ByteExtensions
{
public static bool GetBit(this byte b, int bitNumber) =>
(b & (1 << bitNumber)) != 0;
}
then
byte b = 7;
var bit0 = b.GetBit(3);
I have a byte that represents two values.
First bit represents represents the sequence number.
The rest of the bits represent the actual content.
In C, I could easily parse this out by the following:
typedef struct
{
byte seqNumber : 1;
byte content : 7;
}
MyPacket;
Then I can easily case the input to MyPacket:
char* inputByte = "U"; // binary 01010101
MyPacket * myPacket = (MyPacket*)inputByte;
Then
myPacket->seqNumber = 1
myPacket->content = 42
How can I do the same thing in C#?
Thank you
kab
I would just use properties. Make getters and setters for the two parts that modify the appropriate bits in the true representation.
class myPacket {
public byte packed = 0;
public int seqNumber {
get { return value >> 7; }
set { packed = value << 7 | packed & ~(1 << 7); }
}
public int content {
get { return value & ~(1 << 7); }
set { packed = packed & (1 << 7) | value & ~(1 << 7); }
}
}
C# likes to keep its types simple, so I am betting this is the closest you are getting. Obviously it does not net you the performance improvement in C, but it salvages the meanings.
Hello I'am new to using bytes in C#.
Say if I want to compare bytes based on the forms 0xxxxxxx and 1xxxxxxx. How would I get that first value for my comparison and at the same time remove it from the front?
Any help will be greatly appreciated.
Not sure I understand, but in C#, to write the binaray number 1000'0000, you must use hex notation. So to check if the left-most (most significant) bits of two bytes match, you can do e.g.
byte a = ...;
byte b = ...;
if ((a & 0x80) == (b & 0x80))
{
// match
}
else
{
// opposite
}
This uses bit-wise AND. To clear the most significant bit, you may use:
byte aModified = (byte)(a & 0x7f);
or if you want to assign back to a again:
a &= 0x7f;
You need to use binary operations like
a&10000
a<<1
This will check two bytes and compare each bit. If the bit is the same, it will clear that bit.
static void Main(string[] args)
{
byte byte1 = 255;
byte byte2 = 255;
for (var i = 0; i <= 7; i++)
{
if ((byte1 & (1 << i)) == (byte2 & (1 << i)))
{
// position i in byte1 is the same as position i in byte2
// clear bit that is the same in both numbers
ClearBit(ref byte1, i);
ClearBit(ref byte2, i);
}
else
{
// if not the same.. do something here
}
Console.WriteLine(Convert.ToString(byte1, 2).PadLeft(8, '0'));
}
Console.ReadKey();
}
private static void ClearBit(ref byte value, int position)
{
value = (byte)(value & ~(1 << position));
}
}
I have two numbers (going from 0-9) and I want to combine them into 1 byte.
Number 1 would take bit 0-3 and Number 2 has bit 4-7.
Example : I have number 3 and 4.
3 = 0011 and 4 is 0100.
Result should be 0011 0100.
How can I make a byte with these binary values?
This is what I currently have :
public Byte CombinePinDigit(int DigitA, int DigitB)
{
BitArray Digit1 = new BitArray(Convert.ToByte(DigitA));
BitArray Digit2 = new BitArray(Convert.ToByte(DigitB));
BitArray Combined = new BitArray(8);
Combined[0] = Digit1[0];
Combined[1] = Digit1[1];
Combined[2] = Digit1[2];
Combined[3] = Digit1[3];
Combined[4] = Digit2[0];
Combined[5] = Digit2[1];
Combined[6] = Digit2[2];
Combined[7] = Digit2[3];
}
With this code I have ArgumentOutOfBoundsExceptions
Forget all that bitarray stuff.
Just do this:
byte result = (byte)(number1 | (number2 << 4));
And to get them back:
int number1 = result & 0xF;
int number2 = (result >> 4) & 0xF;
This works by using the << and >> bit-shift operators.
When creating the byte, we are shifting number2 left by 4 bits (which fills the lowest 4 bits of the results with 0) and then we use | to or those bits with the unshifted bits of number1.
When restoring the original numbers, we reverse the process. We shift the byte right by 4 bits which puts the original number2 back into its original position and then we use & 0xF to mask off any other bits.
This bits for number1 will already be in the right position (since we never shifted them) so we just need to mask off the other bits, again with & 0xF.
You should verify that the numbers are in the range 0..9 before doing that, or (if you don't care if they're out of range) you can constrain them to 0..15 by anding with 0xF:
byte result = (byte)((number1 & 0xF) | ((number2 & 0xF) << 4));
this should basically work:
byte Pack(int a, int b)
{
return (byte)(a << 4 | b & 0xF);
}
void Unpack(byte val, out int a, out int b)
{
a = val >> 4;
b = val & 0xF;
}
In C#, how would I go about setting 2 bytes where the first 10 bits represent one decimal value and the next 6 represent a different decimal value?
So if the first value was '8' (first 10 bits) and the second '2' (remaining 6 bits), I need to end up with '0000001000 000010' inside a byte array.
Thanks!
Ad
UInt16 val1 = 8;
UInt16 val2 = 2;
UInt16 combined = (UInt16)((val1 << 6) | val2);
If you need it in a byte array, you can pass the result to the BitConverter.GetBytes method.
byte[] array = BitConverter.GetBytes(combined);
int val1 = 8;
int val2 = 2;
// First byte contains all but the 2 least significant bits from the first value.
byte byte1 = (byte)(val1 >> 2);
// Second byte contains the 2 least significant bits from the first value,
// shifted 6 bits left to become the 2 most significant bits of the byte,
// followed by the (at most 6) bits of the second value.
byte byte2 = (byte)((val1 & 4) << 6 | val2);
byte[] bytes = new byte[] { byte1, byte2 };
// Just for verification.
string s =
Convert.ToString(byte1, 2).PadLeft(8, '0') + " " +
Convert.ToString(byte2, 2).PadLeft(8, '0');
Not accounting for any kind of overflow:
private static byte[] amend(int a, int b)
{
// Combine the datum into a 16 bits integer
var c = (ushort) ((a << 6) | (b));
// Fragment the Int to bytes
var ret = new byte[2];
ret[0] = (byte) (c >> 8);
ret[1] = (byte) (c);
return ret;
}
ushort value = (8 << 6) | 2;
byte[] bytes = BitConverter.GetBytes(value);