我正在创建一个序列化格式,标头的一部分是正文的长度。
为此,我分配固定数量的字节(当前为 4),我想用它来存储尽可能长的数字。
因此,我想将
long
存储在 byte[]
中(我猜这可以称为基数 256?)。
这是我的代码:
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));
}
我做错了什么?
要将
long
值转换为字节数组(即基数 256),您需要使用按位运算。让我们一步步分解吧。
确保您没有超出限制: 4 字节(32 位)空间可以表示从
0
到 2^32 - 1
的值。因此,max
应该是 2^32 - 1
(即 4294967295
),而不是您使用 byte.MaxValue
计算出的总和。
将长整型转换为字节: 要获取组成
long
的字节,您可以执行位掩码和移位。对于要提取的每个字节:
&
的按位与 (0xFF
) 来获取值的最低有效 8 位。这是代码的更正版本:
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
}
这是发生的事情:
0xFF
将获得val
的最低有效8位。val
右移 8 位,这样接下来的 8 位将处于下一次迭代的最低有效位置。这个过程一直持续到我们填满整个 encoded
数组。注意: 处理
val
为负数或超出字节数组范围的情况很重要。上面的代码假设 val
始终为非负数,并且您正在检查最大允许值。如果 val
有可能为负,您需要为此添加另一项检查。