有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

一个字节的最大值为127

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

一个字节的最小值为-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) 个答案

  1. # 1 楼答案

    在这个答案中,我们重点关注所需的的数量。从那时起,字节数可以通过ceil除以8来计算

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

    我假设我们将所有数字存储在2的补码中,因此我们需要5位而不是4位来存储数字8dec=01000bin,依此类推

    对于适合于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;
    }
    
  2. # 2 楼答案

    Long转换为Binary String,然后获取Stringlength

    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

  3. # 3 楼答案

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

    public int countBytesNeeded(long l) {
        if (l == 0) {
            return 1;
        }
    
        int result = 0;
    
        for (; l != 0; result++) {
            l = l / 128;
        }
        return result;
    }
    
  4. # 4 楼答案

    您可以创建一个包含两个字段的枚举:min和max。然后迭代该枚举值,循环中只有一个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;
    }
    
  5. # 5 楼答案

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

    方法^{}可用于此

    由于long有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);
    }
    

    解决方案只需一行代码,不需要循环

  6. # 6 楼答案

    虽然我认为在Java中,对于long原语类型,我们应该将字节数保留为8,但有另一种方法可以计算保存long值(包括符号位)的最小字节数。该方法还可用于计算调整方法签名的任何整数的大小:

    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. 三,