How to parse byte using bits value - c#

I have to get values from a byte saved in three parts of bit combination.
Bit Combination is following
| - - | - - - | - - - |
first portion contains two bits
Second portion contains 3 bits
Third portion contains 3 bits
sample value is
11010001 = 209 decimal
What I want is create Three different Properties which get me decimal value of three portion of given bit as defined above.
how can i get Bit values from this decimal number and then get decimal value from respective bits..

Just use shifting and masking. Assuming that the two-bit value is in the high bits of the byte:
int value1 = (value >> 6) & 3; // 3 = binary 11
int value2 = (value >> 3) & 7; // 7 = binary 111
int value3 = (value >> 0) & 7;
The final line doesn't have to use the shift operator of course - shifting by 0 bits does nothing. I think it adds to the consistency though.
For your sample value, that would give value1 = 3, value2 = 2, value3 = 1.
Reversing:
byte value = (byte) ((value1 << 6) | (value2 << 3) | (value3 << 0));

You can extract the different parts using bit-masks, like this:
int part1=b & 0x3;
int part2=(b>>2) & 0x7;
int part3=(b>>5) & 0x7;
This shifts each part into the least-significant-bits, and then uses binary and to mask all other bits away.
And I assume you don't want the decimal value of these bits, but an int containing their value. An integer is still represented as a binary number internally. Representing the int in base 10/decimal only happens once you convert to string.

Related

Storing 3 different values in a single byte

I am working with a proprietary binary messaging protocol, where in one message a single byte is used to store 3 different values, like so:
Bit
7 IsArray (1 bit)
6 ArrayLength, MSB (4 bits, max size 2^4 = 16)
5
4
3
2 DataType, MSB (3 bits, max size = 2^3 = 8)
1
0
I want to extract these three values, and store them in three different properties in an object, bool IsArray, byte ArrayLength and byte DataType. I also need to go back from these three properties to a single byte
I seldom work at this level, and things got a bit messy when I went beyond setting or getting the single bit for IsArray, to trying to set several at once. I created three different masks that I thought would help me:
var IsArrayMask = 0x80; // 1000 0000
var ArrayLengthMask = 0x78; // 0111 1000
var DataTypeMask = 0x07; // 0000 0111
Is there an elegant way to achieve what I'm going for?
Edit: With some help from #stefankmitph, I discovered I had my shifting all messed up. This is how I go from 3 properties to a single byte now:
bool IsArray = true;
byte ArrayLength = 6;
byte DataType = 3;
byte serialized = 0x00; // Should end up as 1011 0011 / 0xB3
serialized |= (byte)((IsArray ? 1 : 0) << 7 & IsArrayMask);
serialized |= (byte)(ArrayLength << 3 & ArrayLengthMask);
serialized |= (byte)(DataType & DataTypeMask);
And back again, as per the answer below:
bool isArray = (serialized & IsArrayMask) == IsArrayMask;
int arrayLength = (serialized & ArrayLengthMask) >> 3;
int dataType = (serialized & DataTypeMask);
int val = 0xBE; //f.e. 1011 | 1110
var IsArrayMask = 0x80; // 1000 0000
var ArrayLengthMask = 0x78; // 0111 1000
var DataTypeMask = 0x07; // 0000 0111
bool isArray = ((val & IsArrayMask) >> 7) == 1; // output: true
// as pointed out by #PeterSchneider & #knittl
// you can get isArray in a probably more elegant way:
isArray = (val & IsArrayMask) == IsArrayMask;
// i keep both ways in my answer, because i think
// the first one illustrates that you have to shift by 7 to get 1 (true) or 0 (false)
int arrayLength = (val & ArrayLengthMask) >> 3; // output: 7
int dataType = (val & DataTypeMask); // output: 6

How am I getting a single bit from an int?

I understand that:
int bit = (number >> 3) & 1;
Will give me the bit 3 places from the left, so lets say 8 is 1000 so that would be 0001.
What I don't understand is how "& 1" will remove everything but the last bit to display an output of simply "1". I know that this works, I know how to get a bit from an int but how is it the code is extracting the single bit?
Code...
int number = 8;
int bit = (number >> 3) & 1;
Console.WriteLine(bit);
Unless my boolean algebra from school fails me, what's happening should be equivalent to the following:
*
1100110101101 // last bit is 1
& 0000000000001 // & 1
= 0000000000001 // = 1
*
1100110101100 // last bit is 0
& 0000000000001 // & 1
= 0000000000000 // = 0
So when you do & 1, what you're basically doing is to zero out all other bits except for the last one which will remain whatever it was. Or more technically speaking you do a bitwise AND operation between two numbers, where one of them happens to be a 1 with all leading bits set to 0
8 = 00001000
8 >> 1 = 00000100
8 >> 2 = 00000010
8 >> 3 = 00000001
If you use mask 1 = 000000001 then you have:
8 >> 3 = 000000001
1 = 000000001
(8 >> 3) & 1 = 000000001
Actually this is not hard to understand.
the "& 1" operation is just set all bits of the value to the "0", except the bit, which placed in the same position as the valuable bit in the value "1"
previous operation just shifts the all bits to the right. and places the checked bit to the position which won't be setted to "0" after operation "& 1"
fo example
number is 1011101
number >> 3 makes it 0001011
but (number >> 3) & 1 makes it 0000001
When u right shift 8 you get 0001
0001 & 0001 = 0001 which converted to int gives you 1.
So, when a value 0001 has been assigned to an int, it will print 1 and not 0001 or 0000 0001. All the leading zeroes will be discarded.

Merge first n bits of a byte with last 8-n bits of another byte

How can I merge first n bits of a byte with last 8-n bits of another byte?
I know something like below for picking 3 bits from first and 5 from second (Which I have observed in DES encryption algorithm)
zByte=(xByte & 0xE0) | (yByte & 0x1F); But I don't know maths behind why we need to use 0XE0 and 0X1F in this case. So I am trying to understand the details with regards to each bit.
In C#, that would be something like:
int mask = ~((-1) << n);
var result = (x & ~mask) | (y & mask);
i.e. we build a mask that is (for n = 5) : 000....0011111, then we combine (&) one operand with that mask, the other operand with the inverse (~) of the mask, and compose them (|).
You could also probably do something more quickly just using shift operations (avoiding a mask completely) - but only if the data can be treated as unsigned (so Java might struggle here).
It just sounds like you don't understand how boolean arithmetic works? If this is your question it works like this:
0xEO and 0x1F are hexidecimal representations of numbers. If we convert these numbers to binary they would be:
0xE0 = 11100000
0x1F = 00011111
Additionally & (and) and | (or) are bitwise logical operators. To understand logical operators, first remember the 1 = true and 0 = false.
The truth table for & is:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
The truth table for | is:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
So let's breakdown your equation piece by piece. First we will evaluate the code in parenthesis first. We will walk through each number in binary and for the & operator if each operand has a 1 in the same bit position we will return 1. If either number has a 0 then we will return 0. After we finish the evaluation of the operands in the parenthesis we will then take the 2 resulting numbers and apply the | operator bit by bit. If either number has a 1 in the same bit position we will return 1. If both numbers have a 0 in the same bit position we will return 0.
For the sake of discussion, let's say that
xByte = 255 or (FF in hex and 11111111 in binary)
yByte = 0 or (00 in hex and 00000000 in binary)
When you apply the & and | operators we are going to compare each bit one at a time:
zByte = (xByte & 0xEO) | (yByte & 0x1F)
becomes:
zByte = (11111111 & 11100000) | (00000000 & 00011111)
zByte = 111000000 | 00000000
zByte = 11100000
If you understand this and how boolean logic works then you can use Marc Gravell's answer.
The math behind those numbers (0xE0 and 0x1F) is quite simple. First we are exploiting the fact that 0 & <bit> always equals 0 and 1 & <bit> always equals <bit>.
0x1F is 00011111 binary, which means that the first 3 bits will always be 0 after an & operation with another byte - and the last 5 bits will be the same they were in the other byte. Remember that every 1 in a binary number represents a power of 2, so if you want to find the mask mathematically it would be the sum of 2^x from x = 0 to n-1. Then you can find the opposite mask (the one that is 11100000) to extract the first 3 bit, you simply need to subtract the mask from 11111111, and you will get 11100000 (0xE0).
In java,
By using the following function we can get the first n bits of the first Byte and last 8 n bits of the second byte.
public class BitExample {
public static void main(String[] args) {
Byte a = 15;
Byte b = 16;
String mergedValue=merge(4, a, b);
System.out.println(mergedValue);
}
public static String merge(int n, Byte a, Byte b) {
String mergedString = "";
String sa = Integer.toBinaryString(a);
String sb = Integer.toBinaryString(b);
if(n>sa.length()) {
for(int i=0; i<(n-sa.length()); i++) {
mergedString+="0";
}
mergedString+=sa;
}else{
mergedString+=sa.substring(0, n);
}
if(8*n>sb.length()) {
for(int i=0; i<(8*n-sb.length()); i++) {
mergedString+="0";
}
mergedString+=sb;
}
return mergedString;
}
}

Get next smallest Double number

As part of a unit test, I need to test some boundary conditions. One method accepts a System.Double argument.
Is there a way to get the next-smallest double value? (i.e. decrement the mantissa by 1 unit-value)?
I considered using Double.Epsilon but this is unreliable as it's only the smallest delta from zero, and so doesn't work for larger values (i.e. 9999999999 - Double.Epsilon == 9999999999).
So what is the algorithm or code needed such that:
NextSmallest(Double d) < d
...is always true.
If your numbers are finite, you can use a couple of convenient methods in the BitConverter class:
long bits = BitConverter.DoubleToInt64Bits(value);
if (value > 0)
return BitConverter.Int64BitsToDouble(bits - 1);
else if (value < 0)
return BitConverter.Int64BitsToDouble(bits + 1);
else
return -double.Epsilon;
IEEE-754 formats were designed so that the bits that make up the exponent and mantissa together form an integer that has the same ordering as the floating-point numbers. So, to get the largest smaller number, you can subtract one from this number if the value is positive, and you can add one if the value is negative.
The key reason why this works is that the leading bit of the mantissa is not stored. If your mantissa is all zeros, then your number is a power of two. If you subtract 1 from the exponent/mantissa combination, you get all ones and you'll have to borrow from the exponent bits. In other words: you have to decrement the exponent, which is exactly what we want.
The Wikipedia page on double-precision floating point is here: http://en.wikipedia.org/wiki/Double_precision_floating-point_format
For fun I wrote some code to break out the binary representation of the double format, decrements the mantissa and recomposes the resultant double. Because of the implicit bit in the mantissa we have to check for it and modify the exponent accordingly, and it might fail near the limits.
Here's the code:
public static double PrevDouble(double src)
{
// check for special values:
if (double.IsInfinity(src) || double.IsNaN(src))
return src;
if (src == 0)
return -double.MinValue;
// get bytes from double
byte[] srcbytes = System.BitConverter.GetBytes(src);
// extract components
byte sign = (byte)(srcbytes[7] & 0x80);
ulong exp = ((((ulong)srcbytes[7]) & 0x7F) << 4) + (((ulong)srcbytes[6] >> 4) & 0x0F);
ulong mant = ((ulong)1 << 52) | (((ulong)srcbytes[6] & 0x0F) << 48) | (((ulong)srcbytes[5]) << 40) | (((ulong)srcbytes[4]) << 32) | (((ulong)srcbytes[3]) << 24) | (((ulong)srcbytes[2]) << 16) | (((ulong)srcbytes[1]) << 8) | ((ulong)srcbytes[0]);
// decrement mantissa
--mant;
// check if implied bit has been removed and shift if so
if ((mant & ((ulong)1 << 52)) == 0)
{
mant <<= 1;
exp--;
}
// build byte representation of modified value
byte[] bytes = new byte[8];
bytes[7] = (byte)((ulong)sign | ((exp >> 4) & 0x7F));
bytes[6] = (byte)((((ulong)exp & 0x0F) << 4) | ((mant >> 48) & 0x0F));
bytes[5] = (byte)((mant >> 40) & 0xFF);
bytes[4] = (byte)((mant >> 32) & 0xFF);
bytes[3] = (byte)((mant >> 24) & 0xFF);
bytes[2] = (byte)((mant >> 16) & 0xFF);
bytes[1] = (byte)((mant >> 8) & 0xFF);
bytes[0] = (byte)(mant & 0xFF);
// convert back to double and return
double res = System.BitConverter.ToDouble(bytes, 0);
return res;
}
All of which gives you a value that is different from the initial value by a change in the lowest bit of the mantissa... in theory :)
Here's a test:
public static Main(string[] args)
{
double test = 1.0/3;
double prev = PrevDouble(test);
Console.WriteLine("{0:r}, {1:r}, {2:r}", test, prev, test - prev);
}
Gives the following results on my PC:
0.33333333333333331, 0.33333333333333326, 5.5511151231257827E-17
The difference is there, but is probably below the rounding threshold. The expression test == prev evaluates to false though, and there is an actual difference as shown above :)
In .NET Core 3.0 you can use Math.BitIncrement/Math.BitDecrement. No need to do manual bit manipulation anymore
Returns the smallest value that compares greater than a specified value.
Returns the largest value that compares less than a specified value.
Since .NET Core 7.0 there are also Double.BitIncrement and Double.BitDecrement

Bit manipulation in C# using a mask

I need a little help with bitmap operations in C#
I want to take a UInt16, isolate an arbitrary number of bits, and set them using another UInt16 value.
Example:
10101010 -- Original Value
00001100 -- Mask - Isolates bits 2 and 3
Input Output
00000000 -- 10100010
00000100 -- 10100110
00001000 -- 10101010
00001100 -- 10101110
^^
It seems like you want:
(orig & ~mask) | (input & mask)
The first half zeroes the bits of orig which are in mask. Then you do a bitwise OR against the bits from input that are in mask.
newValue = (originalValue & ~mask) | (inputValue & mask);
originalValue -> 10101010
inputValue -> 00001000
mask -> 00001100
~mask -> 11110011
(originalValue & ~mask)
10101010
& 11110011
----------
10100010
^^
Cleared isolated bits from the original value
(inputValue & mask)
00001000
& 00001100
----------
00001000
newValue =
10100010
| 00001000
----------
10101010
Something like this?
static ushort Transform(ushort value){
return (ushort)(value & 0x0C/*00001100*/ | 0xA2/*10100010*/);
}
This will convert all your sample inputs to your sample outputs. To be more general, you'd want something like this:
static ushort Transform(ushort input, ushort mask, ushort bitsToSet){
return (ushort)(input & mask | bitsToSet & ~mask);
}
And you would call this with:
Transform(input, 0x0C, 0xA2);
For the equivalent behavior of the first function.
A number of the terser solutions here look plausible, especially JS Bangs', but don't forget that you also have a handy BitArray collection to use in the System.Collections namespace: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx
If you want to do bitwise manipulations, I have written a very versatile method to copy any number of bits from one byte (source byte) to another byte (target byte). The bits can be put to another starting bit in the target byte.
In this example, I want to copy 3 bits (bitCount=3) from bit #4 (sourceStartBit) to bit #3 (destinationStartBit). Please note that the numbering of bits starts with "0" and that in my method, the numbering starts with the most significant bit = 0 (reading from left to right).
byte source = 0b10001110;
byte destination = 0b10110001;
byte result = CopyByteIntoByte(source, destination, 4, 1, 3);
Console.WriteLine("The binary result: " + Convert.ToString(result, toBase: 2));
//The binary result: 11110001
byte CopyByteIntoByte(byte sourceByte, byte destinationByte, int sourceStartBit, int destStartBit, int bitCount)
{
int[] mask = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
byte sourceMask = (byte)(mask[bitCount] << (8 - sourceStartBit - bitCount));
byte destinationMask = (byte)(~(mask[bitCount] << (8-destStartBit - bitCount)));
byte destinationToCopy = (byte)(destinationByte & destinationMask);
int diff = destStartBit - sourceStartBit;
byte sourceToCopy;
if(diff > 0)
{
sourceToCopy = (byte)((sourceByte & sourceMask) >> (diff));
}
else
{
sourceToCopy = (byte)((sourceByte & sourceMask) << (diff * (-1)));
}
return (byte)(sourceToCopy | destinationToCopy);
}

Categories

Resources