Integer to byte with given number of bits set - c#

I don't know what to call this, which makes googling harder.
I have an integer, say 3, and want to convert it to 11100000, that is, a byte with the value of the integers number of bits set, from the most significantly bit.
I guess it could be done with:
byte result = 0;
for(int i = 8; i > 8 - 3; i--)
result += 2 ^ i;
but is there anything faster / more nice or, preferably, standard library included in .net?

int n = 3; // 0..8
int mask = 0xFF00;
byte result = (byte) (mask >> n);

Because there are only a few possibilities, you could just cache them:
// Each index adds another bit from the left, e.g. resultCache[3] == 11100000.
byte[] resultCache = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0XF8, 0xFC, 0xFE, 0xFF };
You'd also get an exception instead of a silent error if you accidentally tried to get the value for n > 8.

Related

C# Converting an int into an array of 2 bytes

I apologize in advance if my question is not clear enough, I don't have a lot of experience with c# and I encounter an odd problem.
I am trying to convert an int into an array of two bytes (for example: take 2210 and get: 0x08, 0xA2), but all I'm getting is: 0x00, 0xA2, and I can't figure out why. Would highly appreciate any advice.
(I've tried reading other questions regarding this matter, but couldn't find an helpful answer)
my code:
profile_number = GetProfileName(); // it gets the int
profile_num[0] = (byte) ((profile_number & 0xFF00));
profile_num[1] = (byte) ((profile_number & 0x00FF));
profile_checksum = CalcProfileChecksum();
//Note: I'm referring to a 2-byte array, so the answer to the question regarding 4-byte arrays does not help me.
You need to shift the 1st byte:
//profile_num[0] = (byte) ((profile_number & 0xFF00));
profile_num[0] = (byte) ((profile_number & 0xFF00) >> 8);
profile_num[1] = (byte) ((profile_number & 0x00FF));
First I thought that this is the simplest way:
public static byte[] IntToByteArray(int value)
{
return (new BigInteger(value)).ToByteArray();
}
But i realised that ToByteArray returns only needed bytes. If the value is small (under 256) then a single byte will be returned. Another thing that I noticed is that values are reversed in the returned array so that the byte that is in the right (the most insignificant byte) is found in the left. So I come with a little revision:
public static byte[] IntToByteArrayUsingBigInteger(int value, int numberOfBytes)
{
var res = (new BigInteger(value)).ToByteArray().Reverse().ToArray();
if (res.Length == numberOfBytes)
return res;
byte[] result = new byte[numberOfBytes];
if (res.Length > numberOfBytes)
Array.Copy(res, res.Length - numberOfBytes, result, 0, numberOfBytes);
else
Array.Copy(res, 0, result, numberOfBytes - res.Length, res.Length);
return result;
}
I know that this does not compare with the performance of having bitwise operations but for the sake of learning new things and if you prefeer to use high level classes that .NET provides instead of going low level and use bitwise operators i think it's a nice alternative.

Conversion of byte array hex to decimal

I have a byte array with hexadecimal values, for example:
var b = new byte[] {0x27, 0x01, 0x00, 0x00};
I need to convert this to decimal value, but when I used code below, get unexpected result. Expected is 295, but result is 654376960.
if (BitConverter.IsLittleEndian) Array.Reverse(b);
//int myInt = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
int value = BitConverter.ToInt32(b, 0);
What's wrong?
Basically your understanding of endianness is wrong - your example is in little-endian format already, so you should only reverse it if BitConverter expects a big-endian format. You just need to invert your condition:
if (!BitConverter.IsLittleEndian) Array.Reverse(b);
(I'd personally put the body of the if statement in braces and new lines, but that's a different matter.)

How to add multiple bytes and get a byte array?

Given a byte array
byte[] someBytes = { 0xFF, 0xFE, 0xFE, 0xFF, 0x11, 0x00 ,0x00 ,0x00 ,0x00}
What's the best to add up all the bytes? Manually adding all of the bytes by hand as hex numbers would yield 40B on my above example so preferably I'd like to end up with something like:
byte[] byteSum = { 0x04, 0x0B }
Actually, all I really need is the 0x0B part (Used for checksum). Checksum is calculated by 0x0B XOR 0x55 (Which yields 0x5E) in this case.
I understand this isn't a normal addition of bytes, but this is how the checksum is calculated.
Manually looping through the byte array and adding them results in an integer sum.
What's the most concise way of doing this?
erm,
byte checksum;
foreach (var b in someBytes)
{
checksum = (byte)((checksum + b) & 0xff);
}
I'm not sure if I understand your question... But this is how I would do it:
byte sum = 0;
foreach (byte b in someBytes)
{
unchecked
{
sum += b;
}
}
But this does not yield 0x0B, but 0x69.
Using LINQ's sum and casting to byte in the end:
unchecked
{
var checksum = (byte)(someBytes.Sum(b => (long)b) ^ 0x55);
}

How do I properly loop through and print bits of an Int, Long, Float, or BigInteger?

I'm trying to debug some bit shifting operations and I need to visualize the bits as they exist before and after a Bit-Shifting operation.
I read from this answer that I may need to handle backfill from the shifting, but I'm not sure what that means.
I think that by asking this question (how do I print the bits in a int) I can figure out what the backfill is, and perhaps some other questions I have.
Here is my sample code so far.
static string GetBits(int num)
{
StringBuilder sb = new StringBuilder();
uint bits = (uint)num;
while (bits!=0)
{
bits >>= 1;
isBitSet = // somehow do an | operation on the first bit.
// I'm unsure if it's possible to handle different data types here
// or if unsafe code and a PTR is needed
if (isBitSet)
sb.Append("1");
else
sb.Append("0");
}
}
Convert.ToString(56,2).PadLeft(8,'0') returns "00111000"
This is for a byte, works for int also, just increase the numbers
To test if the last bit is set you could use:
isBitSet = ((bits & 1) == 1);
But you should do so before shifting right (not after), otherwise you's missing the first bit:
isBitSet = ((bits & 1) == 1);
bits = bits >> 1;
But a better option would be to use the static methods of the BitConverter class to get the actual bytes used to represent the number in memory into a byte array. The advantage (or disadvantage depending on your needs) of this method is that this reflects the endianness of the machine running the code.
byte[] bytes = BitConverter.GetBytes(num);
int bitPos = 0;
while(bitPos < 8 * bytes.Length)
{
int byteIndex = bitPos / 8;
int offset = bitPos % 8;
bool isSet = (bytes[byteIndex] & (1 << offset)) != 0;
// isSet = [True] if the bit at bitPos is set, false otherwise
bitPos++;
}

Converting int value into 3 byte array (and vice versa)

I am working on a C# WinForms application that reads/writes data to/from a hardware device. My application has a multiselect listbox which contains the numbers 1 - 100000 and the user may select up to 10 numbers. When they're done selecting each number, the user clicks a button and my event handler code needs to build a fixed-size (30 bytes) byte array using 3 bytes to represent each selected number and pad the array if less than 10 numbers were selected.
As an example, suppose my user chooses the following values:
17
99152
3064
52588
65536
I'm currently using this code to convert each number into a byte array:
byte[] bytes = BitConverter.GetBytes(selectedNumber);
Array.Reverse(bytes) // because BitConverter.IsLittleEndian() = true
Debug.WriteLine(BitConverter.ToString(bytes));
For the numbers I listed above, this produces the following:
00-00-00-11
00-01-83-50
00-00-0B-F8
00-00-CD-6C
00-01-00-00
BitConverter is giving me back a 4 byte array where I only have space to use 3 bytes to store each number in the final byte array. I can drop the most significant byte of each individual byte array and then build my final array like this:
00-00-11-01-83-50-00-0B-F8-00-CD-6C-01-00-00-[padding here]
Writing that to the device should work. But reading the array (or a similar array) back from the device causes a bit of a problem for me. When I have a 3 byte array and try to convert that into an int using this code...
int i = BitConverter.ToInt32(bytes, 0);
...I get "Destination array is not long enough to copy all the items in the collection." I suppose I could insert a most significant byte of 0x00 at the beginning of every three bytes and then convert that but is there a better way to do this?
I would imagine bit shifting and the | operator should be the most efficient way of doing this.
int i = (bytes[2] << 0) | (bytes[1] << 8) | (bytes[0] << 16);
Also, as a heads up, you're dropping the most significant byte, not the least significant byte ;p
byte[] bytes = new byte[] { 0x00, 0x00, 0x11, 0x01, 0x83, 0x50, 0x00, 0x0B, 0xF8 };
var ints = bytes.Select((b, i) => new { b, i })
.GroupBy(x => x.i / 3)
.Select(g => BitConverter.ToInt32(
new byte[] { 0 }.Concat(g.Select(x => x.b))
.Reverse()
.ToArray(),
0))
.ToArray();
or classically
var ints = new List<int>();
for (int i = 0; i < bytes.Length; i+=3)
{
int intI=0;
for (int j = i; j < i + 3; j++)
{
intI = intI * 256 + bytes[j]; //or (intI << 8) + bytes[j];
}
ints.Add(intI);
}
ints will be 17, 99152 and 3064

Categories