问题
Given an integer value, I need some way to find out the minimum number of bytes needed to store the value. The value may be signed or unsigned, up to 64-bit. Also take the sign bit into account for signed integers.
For example:
8 requires 1 byte at minimum
unsigned 255 requires 1 byte at minimum
signed 255 requires 2 bytes at minimum
4351 requires 2 bytes at minimum
-4294967296 requires 5 bytes at minimum
unsigned 0xFFFFFFFFFFFFFFFF requires 8 bytes at minimum
I can think of a quick-and-dirty way to solve this, using many if-statements, but there might be better (e.g. simpler, cleverer, faster) ways to do this. You may either assume a method with signature int (long value, bool signed)
or two methods int (long value)
(for signed) and int (ulong value)
(for unsigned).
回答1:
Let me give it a go at my own question. As far as I can tell, this is a correct solution, but it may not be optimal in speed, conciseness:
public static int GetMinByteSize(long value, bool signed)
{
ulong v = (ulong)value;
// Invert the value when it is negative.
if (signed && value < 0)
v = ~v;
// The minimum length is 1.
int length = 1;
// Is there any bit set in the upper half?
// Move them to the lower half and try again.
if ((v & 0xFFFFFFFF00000000) != 0)
{
length += 4;
v >>= 32;
}
if ((v & 0xFFFF0000) != 0)
{
length += 2;
v >>= 16;
}
if ((v & 0xFF00) != 0)
{
length += 1;
v >>= 8;
}
// We have at most 8 bits left.
// Is the most significant bit set (or cleared for a negative number),
// then we need an extra byte for the sign bit.
if (signed && (v & 0x80) != 0)
length++;
return length;
}
回答2:
static int BytesForNum(long value, bool signed)
{
if (value == 0)
return 1;
if (signed)
{
if (value < 0)
return CalcBytes(2 * (-1-value));
else
return CalcBytes(2 * value);
}
else
{
if (value < 0)
throw new ArgumentException("Can't represent a negative unsigned number", "value");
return CalcBytes(value);
}
}
//should only be called with positive numbers
private static int CalcBytes(long value)
{
int bitLength = 0;
while (value > 0)
{
bitLength++;
value >>= 1;
}
return (int)(Math.Ceiling(bitLength * 1.0 / 8));
}
I might not have the signed code exactly right, but that's the general idea.
来源:https://stackoverflow.com/questions/11650222/minimum-number-of-bytes-that-can-contain-an-integer-value