我的int的字节数

时间:2012-10-29 15:59:02

标签: java byte

我想知道我的整数字节的大小。示例:

public static void main(String[] args) throws IOException {
   int a = 256;
   System.out.println(nbBytes(a));
}

static byte nbBytes(int value) {
   byte l = 0;
   while (value != 0) {
      value >>>= 8;
      ++l;
   }
   return l;
}

它完美无缺,但我想优化这个计算。 你有一个主张吗? :d

3 个答案:

答案 0 :(得分:2)

如果您的意思是运行时性能,则以下算法(最初找到最高设置位)可能是最快的。我已经修改它以返回编码整数参数所需的字节数:

private static final int[] DE_BRUIJN_BIT_POSITION_LUT = {
      0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
      8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
    };

public static int nbBytes2(int n) {
    n |= n >> 1;  
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    return DE_BRUIJN_BIT_POSITION_LUT[((n * 0x07C4ACDD) >> 27) & 0x1f] / 8 + 1;
}

即使它看起来更复杂,它也没有任何循环或条件处理,这样可以最佳地利用现代CPU流水线。

将De Bruijn算法与您的方法进行比较,对于0x0-0xff范围内的输入,您的方法快4倍(您的方法也不会分支)。对于0x100-0xfff范围内的输入,我的方法快19倍,输入0x10000-0xffffff快28倍,输入> 0x1000000快35倍。所有数字对我的硬件都有效,在其他计算机上它当然可能不同。

答案 1 :(得分:1)

在Java中,int始终是32位,带符号的二进制补码值。例如,请参阅Section 2.3 of the Java Virtual Machine Specification

如果您想知道存储特定值的最小位数,可以使用Integer.numberOfLeadingZeros来获取该值:

int bitsNeeded = 32 - Integer.numberOfLeadingZeros(value);

然后你可以向上舍入以获得所需的字节数。

如果您运行的是不包含此功能的旧版Java,请参阅以下1.6源代码:

public static int numberOfLeadingZeros(int i) {
    if (i == 0)
        return 32;
    int n = 1;
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    n -= i >>> 31;
    return n;
}

这是否比你现在所做的更有效只能通过剖析来确定。它也将取决于您期望遇到的值的分布。

如果你只想要处理非负值,我会这样做:

static byte nBytes(int value) {
    if (value < (1 << 8)) return 1;
    if (value < (1 << 16)) return 2;
    if (value < (1 << 24)) return 3;
    return 4;
}

这假设您需要1个字节来表示零。要处理负数,有两个合理的选择:

  1. 始终返回4
  2. 返回表示2的补码中所需的最小字节数。
  3. 对于第二种情况,我会做以下事情:

    static byte nBytes(int value) {
        if (value < 0) {
            if (value > Integer.MIN_VALUE) {
                value = -value;
                if (value < (1 << 7)) return 1;
                if (value < (1 << 15)) return 2;
                if (value < (1 << 23)) return 3;
            }
        } else {
            if (value < (1 << 8)) return 1;
            if (value < (1 << 16)) return 2;
            if (value < (1 << 24)) return 3;
        }
        return 4;
    }
    

答案 2 :(得分:0)

我不知道这是更优化,但另一种解决方案是(未经测试):

return (byte)Math.ceil(Integer.toBinaryString(value).length()/8.0);