I’m creating a serialisation format, and part of the header is the length of the body.
To do this, I’m allocating a fixed number of bytes (currently 4) which I want to use to store as long a number as possible.
As a result I want to store a long in a byte[] (I guess this could be called base 256?).
Here is my code:
long val = 25484394;
var encoded = new byte[4];
var max = 0L;
for (var i = 0; i < encoded.Length; ++i)
{
max += (long)Math.Pow((int)byte.MaxValue, i);
}
if (val >= max)
throw new ArgumentOutOfRangeException("value", $"{val} is too large to be encoded (max value is {max})");
for (var i = encoded.Length - 1; i > 0; i--)
{
//This line is wrong
encoded[i] = (byte)(int)Math.Floor(val / Math.Pow(byte.MaxValue, i));
}
What am I doing wrong?
>Solution :
To convert a long value to a byte array (i.e., base 256), you’ll need to use bitwise operations. Let’s break it down step by step.
Ensure you’re not going over the limit:
A 4-byte (32-bit) space can represent values from 0 to 2^32 - 1. So, max should be 2^32 - 1 (which is 4294967295), not the sum you calculated using byte.MaxValue.
Converting the long to bytes:
To obtain the bytes that make up a long, you can perform bit masking and shifting. For each byte you want to extract:
- Use bitwise AND (
&) with a mask of0xFFto obtain the least significant 8 bits of the value. - Store the result in your byte array.
- Right-shift the original value by 8 bits to move on to the next byte.
Here’s a corrected version of your code:
long val = 25484394;
var encoded = new byte[4];
// A 4-byte (32-bit) space can represent values from 0 to 2^32 - 1.
long max = (1L << 32) - 1;
if (val > max)
throw new ArgumentOutOfRangeException("value", $"{val} is too large to be encoded (max value is {max})");
for (var i = 0; i < encoded.Length; i++)
{
encoded[encoded.Length - 1 - i] = (byte)(val & 0xFF);
val >>= 8; // Right shift the value by 8 bits
}
Here’s what’s happening:
- The mask
0xFFwill get the least significant 8 bits ofval. - After we’ve taken these bits and stored them, we shift
valright by 8 bits so the next 8 bits will be in the least significant position for the next iteration. This process continues until we’ve filled the entireencodedarray.
Note: It’s important to handle situations where val is negative or beyond the range of the byte array. The code above assumes val is always non-negative and you’re doing a check for the maximum allowable value. If there’s a chance val can be negative, you’ll need to add another check for that.