返回存储长值所需的字节数的函数

时间:2018-06-19 16:10:58

标签: java

我创建了一个函数,该函数返回存储长值所需的字节数。该值必须位于[Long.MIN_VALUE, Long.MAX_VALUE].

private static final int ONE_BYTE_MAX = (1 << 7) - 1; // 127

ONE_BYTE_MAX的值为127

private static final int ONE_BYTE_MIN = -(1 << 7);  // -128

ONE_BYTE_MIN的值为-128

private static final int TWO_BYTE_MAX = (1 << 15) - 1; 

private static final int TWO_BYTE_MIN = -(1 << 15);

private static final int THREE_BYTE_MAX = (1 << 23) - 1; 

private static final int THREE_BYTE_MIN = -(1 << 23);

private static final long FOUR_BYTE_MAX = (1L << 31) - 1;

private static final long FOUR_BYTE_MIN = -(1L << 31);

private static final long FIVE_BYTE_MAX = (1L << 39) - 1; 

private static final long FIVE_BYTE_MIN = -(1L << 39);

private static final long SIX_BYTE_MAX = (1L << 47) - 1; 

private static final long SIX_BYTE_MIN = -(1L << 47);

private static final long SEVEN_BYTE_MAX = (1L << 55) - 1; 

private static final long SEVEN_BYTE_MIN = -(1L << 55);

方法

public static int getBytesForLongValue(long value) {
        if (value >= ONE_BYTE_MIN && value <= ONE_BYTE_MAX) {
            return 1;
        } else if (value >= TWO_BYTE_MIN && value <= TWO_BYTE_MAX) {
            return 2;
        } else if (value >= THREE_BYTE_MIN && value <= THREE_BYTE_MAX) {
            return 3;
        } else if (value >= FOUR_BYTE_MIN && value <= FOUR_BYTE_MAX) {
            return 4;
        }else if (value >= FIVE_BYTE_MIN && value <= FIVE_BYTE_MAX) {
            return 5;
        }else if (value >= SIX_BYTE_MIN && value <= SIX_BYTE_MAX) {
            return 6;
        }else if (value >= SEVEN_BYTE_MIN && value <= SEVEN_BYTE_MAX) {
            return 7;
        } else {
            return 8;
        }
    }  

在Java中有一种简单的方法

6 个答案:

答案 0 :(得分:3)

尽管我认为对于Java中的长原始类型,我们应该将字节数保留为8,但是还有另一种方法来计算保留长值(包括符号位)的最小字节数。同样,该方法也可以用于计算任何整数的大小,从而调整方法的签名:

public static int getMinNoOfBytes(BigInteger value)

不过,这里是代码:

public class Answer {

    public static int getMinNoOfBytes(long value) {
        BigInteger any = BigInteger.valueOf(value);
        return any.toByteArray().length;
    }


    //Test
    public static void main(String[] args) {

        //Long.MAX_VALYE
        System.out.println(getMinNoOfBytes(Long.MAX_VALUE));

        //Long.MIN_VALUE
        System.out.println(getMinNoOfBytes(Long.MIN_VALUE));

        //Any value
        System.out.println(getMinNoOfBytes(65536));

    }
}

输出是(按预期)

8 8 3

答案 1 :(得分:1)

您可以创建一个包含两个字段的枚举:最小值和最大值。然后遍历该枚举值,并在循环内只有一个if语句:

public enum Range {

    ONE  (1, -(1L << 7 ), (1L << 7 ) - 1),
    TWO  (2, -(1L << 15), (1L << 15) - 1),
    THREE(3, -(1L << 23), (1L << 23) - 1),
    FOUR (4, -(1L << 31), (1L << 31) - 1),
    FIVE (5, -(1L << 39), (1L << 39) - 1),
    SIX  (6, -(1L << 47), (1L << 47) - 1),
    SEVEN(7, -(1L << 55), (1L << 55) - 1);

    public final int bytesNeeded;
    public final long min;
    public final long max;

    Range(int bytesNeeded, long min, long max) {
        this.bytesNeeded = bytesNeeded;
        this.min = min;
        this.max = max;
    }

    public static int getNbBytesForLongValue(long value) {
        for (Range range : Range.values()) {
            if (range.min <= value && value <= range.max) {
                return range.bytesNeeded;
            }
        }
        return 8;
    }

}

编辑:

看看这些枚举定义,实际上很容易将其完全转换成循环:

public static int getNbBytesForLongValue(long value) {
    for (int i = 0; i < 7; i++) {
        if (-(1L << (7 + i * 8)) <= value && value <= (1L << (7 + i * 8)) - 1) {
            return i + 1;
        }
    }
    return 8;
}

答案 2 :(得分:1)

您需要找到最高的1位,然后知道可能需要多少字节。

可以使用方法Long.numberOfLeadingZeros(long i)

由于长整数有Long.SIZE位(实际上是64位),因此很容易计算,但是您需要对零值和负值进行特殊处理。

public static int getNbBytesForLongValue1(long value) {
    if (value == 0)
        return 1;
    int bitLength;
    if (value > 0) {
        int leadingZeroes = Long.numberOfLeadingZeros(value);
        bitLength = Long.SIZE - leadingZeroes + 1/*positive sign bit*/;
    } else {
        int leadingOnes = Long.numberOfLeadingZeros(value ^ -1L);
        bitLength = Long.SIZE - leadingOnes + 1/*negative sign bit*/;
    }
    return (bitLength + 7) / 8; // round up to whole bytes
}

可以缩短为(如果您想让自己有点晦涩):

public static int getNbBytesForLongValue(long value) {
    return (value == 0 ? 1 : ((Long.SIZE - Long.numberOfLeadingZeros(value > 0 ? value : value ^ -1L)) >> 3) + 1);
}

一行代码的解决方案,没有循环。

答案 3 :(得分:1)

在此答案中,我们重点关注所需的位数。从那以后,可以通过将ceil除以8来计算字节数。

int bytesNeeded(long number) {
    return (bitsNeeded(number) + 7) / 8;
}

我假设我们将所有数字都存储在二进制补码中,因此我们需要5位而不是4位来存储数字8 dec = 0 1000 bin 等。

适用于long

的数字
int bitsNeeded(long number) {
    if (number < 0) {
        number = ~number; // same as -(number + 1)
    }
    return Long.SIZE - Long.numberOfLeadingZeros(number) + 1;
}

结果

 i | bitsNeeded(i) | binary representation of i in two's complement
---+---------------+-----------------------------------------------
-8 |      4        |  1000
-7 |      4        |  1001
-6 |      4        |  1010
-5 |      4        |  1011
-4 |      3        |   100
-3 |      3        |   101
-2 |      2        |    10
-1 |      1        |     1
 0 |      1        |     0
 1 |      2        |    01
 2 |      3        |   011
 3 |      3        |   011
 4 |      4        |  0100
 5 |      4        |  0101
 6 |      4        |  0110
 7 |      4        |  0111
 8 |      5        | 01000

获取更大的数字

如果您对更大的数字感兴趣,可以将它们存储在BigInteger中。幸运的是,BigInteger为您提供了一种非常方便的方法:

int bitsNeeded(BigInteger number) {
     return number.bitLength() + 1;
}

如果您不关心大数字,但想使用bitLength(),请使用

int bitsNeeded(long number) {
     return BigInteger.valueOf(number).bitLength() + 1;
}

答案 4 :(得分:0)

Long转换为Binary String,然后获得length中的String

public static int getNbBytesForLongValue(long value) {
    int length = Long.toBinaryString(value).length();
    int noOfByte = length%8 == 0 ? length/8 : (length/8 + 1);
    return noOfByte;
}

注意:负数存储为2的称赞。因此,-10将存储为1111111111111111111111111111111111111111111111111111111111110110。因此,您将获得8作为输出(正确)而不是2

答案 5 :(得分:0)

您可以使用for循环将参数除以128,然后计算达到0所需的迭代次数。

public int countBytesNeeded(long l) {
    if (l == 0) {
        return 1;
    }

    int result = 0;

    for (; l != 0; result++) {
        l = l / 128;
    }
    return result;
}