美文网首页
Java中整数基础知识

Java中整数基础知识

作者: Java编程日记 | 来源:发表于2022-03-15 15:39 被阅读0次

    整数基础
    Java中,整数都是有符号的,最高位是符号位,0表示正数,1表示负数。有四种,byte,short,int和long。

    byte 8位,-2 7 ~ 2 7 - 1,-128 ~ 127, 0x80 ~ 0x7F
    short 16位,-2 15 ~ 2 15 - 1,-32768 ~ 32767, 0x8000 ~ 0x7FFF
    int 32位,-2 31 ~ 2 31 -1,-2147483648 ~ 2147483647, 0x8000000 ~ 0x7FFFFFFF
    System.out.println(String.format("Max byte %d, 0x%X, half 0x%X", Byte.MAX_VALUE, Byte.MAX_VALUE, Byte.MAX_VALUE/2));
    System.out.println(String.format("Min byte %d, 0x%X, half 0x%X", Byte.MIN_VALUE, Byte.MIN_VALUE, (byte)(Byte.MIN_VALUE/2)));
    System.out.println(String.format("Max short %d, 0x%X, half 0x%X", Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE/2));
    System.out.println(String.format("Min short %d, 0x%X, half 0x%X", Short.MIN_VALUE, Short.MIN_VALUE, (short) (Short.MIN_VALUE/2)));
    System.out.println(String.format("Max Int %d, 0x%X, half 0x%X", Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE/2));
    System.out.println(String.format("Min Int %d, 0x%X, half 0x%X", Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE/2));

    // Outputs
    //Max byte 127, 0x7F, half 0x3F
    //Min byte -128, 0x80, half 0xC0
    //Max short 32767, 0x7FFF, half 0x3FFF
    //Min short -32768, 0x8000, half 0xC000
    //Max Int 2147483647, 0x7FFFFFFF, half 0x3FFFFFFF
    //Min Int -2147483648, 0x80000000, half 0xC0000000
    细节和原理
    值得注意的是,16进制的数值与直觉预期并不一样,特别是负数。正数是一致的,比如int,一共是32位,最高位是符号,所以真正数值部分是31位,那么最大的int就是0x7FFFFFF。

    但负数,也即是最小的int,却与直觉完全不一样。按照直觉,负数最高位是1,那最小的int应该是0xFFFFFFFF啊,为何确是0x80000000呢?原因就是整数的编码方式并不是直接的二进制形式的,是以 补码的形式 ,也就是说在内部实现中,用二进制表示一个整数的时候,是以二进制补码形式(转成二进制后还要求其补码,才是真实的二进制和16进制形式)。

    简单来说,补码是一种二进制编码形式,正数的补码就是它的本身,而负数的补码是其取反后加1,可以 参考百科上的定义 。

    负数的转换:原码取反加1,即是补码,补码减1再取反即是原码,符号位在转换过程中一直不变。

    非10进制字面常量是补码形式
    在日常代码中,为了方便,通常都用16进制来写一些整数常量,这里就特别要注意了。16进制的字面常量,不会再进行补码转换,会当成补码直接使用。

    System.out.println(String.format("Literal %d, 0x%X", 0xffffffff, 0xffffffff));
    //Literal -1, 0xFFFFFFFF
    所以,你写的0xFFFFFFFF是补码形式,它的原码是减1再取反,(32个1)减1,最低位变成0,前面31个1,再取反,就只剩下最后一位是1和最高位的符号位,因此是-1,注意符号位是不变的,在转换过程中。

    而最小的整数是-2 31 ,原码 形式应该是0x80000000,先取反变成了0xFFFFFFFF,再加1,符号位最高位不变的情况下,其余全变成了0,所以是0x80000000。

    最小整数
    开篇时说了,当时错误的认为0xFFFFFFFF是最小的整数,这里犯的第一个严重错误是,误把二进制的原码当成了补码,代码中的16进制(二进制)都是补码形式的,它的原码是0x10000001即-1。这个错误是比较明显的。

    但另外的问题就是,假如都是二进制原码的情况下,为啥最小的整数是0x80000000而不是0xFFFFFFFFF。这是理解上的误区,整数的定义是,最高位是符号位,所以常规认知是全是1的情况是最大的数,加上符号不就变成最小的了么?这是以10进制思维,也就是二进制转换成为10进制后的想法。计算机只认识二进制,在最高位是1(负数)的情况下,哪个数最小?当然0x80000000最小啊,它除了符号位全是0,肯定 小于0xFFFFFFFF,因此从二进制的角度来理解,0x80000000是最小的整数。

    而0xFFFFFFFF(原码)则是最大的负整数,最高位是符号位,其余31位全是1,肯定 最大啊,当然 了最大的负数是-1。

    一些有意思的值
    Integer.MAX_VALUE + 1 = Integer.MIN_VALUE
    按理说应该溢出了,但如果以16进制去计算,就是这样的结果:0x7FFFFFFF + 1 = 0x80000000

    System.out.println(String.format("Max in %d (0x%X) + 1 = %d (0x%X)", Integer.MAX_VALUE, Integer.MAX_VALUE, (Integer.MAX_VALUE+1), (Integer.MAX_VALUE+1)));
    // Max in 2147483647 (0x7FFFFFFF) + 1 = -2147483648 (0x80000000)
    Integer.MIN_VALUE - 1 = Integer.MAX_VALUE
    System.out.println(String.format("Min in %d (0x%X) - 1 = %d (0x%X)", Integer.MIN_VALUE, Integer.MIN_VALUE, (Integer.MIN_VALUE-1), (Integer.MIN_VALUE-1)));
    //Min in -2147483648 (0x80000000) - 1 = 2147483647 (0x7FFFFFFF)

    相关文章

      网友评论

          本文标题:Java中整数基础知识

          本文链接:https://www.haomeiwen.com/subject/fkjydrtx.html