【问题标题】:Minimum number of bytes that can contain an integer value可以包含整数值的最小字节数
【发布时间】:2012-07-25 12:56:29
【问题描述】:

给定一个整数值,我需要一些方法来找出存储该值所需的最小字节数。该值可以是有符号或无符号的,最高可达 64 位。对于有符号整数,还要考虑符号位。

例如:

                          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

我可以想到一种快速而简单的方法来解决这个问题,使用许多 if 语句,但可能有更好的(例如更简单、更聪明、更快)的方法来解决这个问题。您可以假设一个带有签名int (long value, bool signed) 的方法或两个方法int (long value)(用于签名)和int (ulong value)(用于未签名)。

【问题讨论】:

  • 你需要两个输入(long val,bool signed),对吧?
  • 正确,(long value, bool signed) 将满足签名或未签名的要求,最高 64 位。但也可能是两种方法,一种(long value)另一种(ulong value)

标签: c# integer bit-manipulation


【解决方案1】:

让我试一试我自己的问题。据我所知,这是一个正确的解决方案,但在速度、简洁性方面可能不是最佳的:

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));
    }
    

    我可能没有完全正确的签名代码,但这是一般的想法。

    【讨论】:

    • 所以如果我传递值 ((long)UInt64.MaxValue, false) 那么我得到一个异常?
    • 如果您尝试在 unchecked 上下文之外执行此操作,您将收到编译错误。但这带来了一个好点:如果value 大于大约long.MaxValue / 2 并且signedtrue,我的代码将失败。一个简单的 if 就可以解决这个问题。
    • 那个CalcBytes函数真的保存了吗? Math.Log 是否保证足够准确?
    • 好点。我已经用移位代码替换了它。那应该是完全准确的。
    • 您的代码无法处理我帖子中的所有情况(更准确地说,签名时大于Int64.MaxValue 的任何数字都是false)并且至少对于0x80000000000000000xFFFFFFFFFFFFFFFF (-1 ) 并签名0x7FFFFFFFFFFFFFFF,因为它返回值 0,这显然是错误的。而且-1-x~x不一样吗?
    猜你喜欢
    • 1970-01-01
    • 2015-05-14
    • 1970-01-01
    • 2022-01-23
    • 2018-02-07
    • 2020-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多