美文网首页互联网开发
Java int 类型数值越界引发的思考

Java int 类型数值越界引发的思考

作者: bigzuo | 来源:发表于2018-08-26 17:34 被阅读0次

    原创文章,如需转载,请注明来自:https://www.jianshu.com/u/e2917208bd0d

    今天在重写Twitter 的分布式ID生成算法 sonw flake算法时,遇到一个问题,即一个整数在多次相乘后,输出的结果是0!对应的测试程序如下:

    int a = 1;
    System.out.println(a);
    for (int i =2;i<42;++i) {
        a = a*2;
    }
    System.out.println(a);
    
    

    后来思考了一下才反应过来,这个相乘的结果,远超过了Java int类型可以表示的范围。Java int类型可以表示的范围才是-2^{31}2^{31}-1

    但是为什么输出结果是0呢?

    因为计算机在存储数据时,最高位表示的是符号位,0表示正数,1表示负数,并且计算机中的数据使用补码来表示的。正数的补码是其本身,而负数的补码则是其反码加1(不包括符号位).
    因为在执行“a = a2”,当a=2^{31}*时,在计算机中的表示已经变成变成了“10000000 00000000 00000000 00000000”,然后计算机在读取这个值的时候,就会把它当成负数来读,然后对应的值就是最小负数:-2147483648。

    接下来,当执行到a=2^{32},理论上值已经变成“1 00000000 00000000 00000000 00000000”,即33位,但是计算机在读取int类型时,只会读取32位,因此会舍弃掉最前面的“1”,因此读出来的结果就是0.

    下面以short类型举例,说明一下数字在计算机中二进制的存储方式:
    <p>最小的负整数 -32768        计算机中二进制标示:10000000   00000000</p>
    <p>最大的负整数-1      计算机中二进制标示:11111111  11111111</p>
    <p>0           计算机中二进制标示:00000000  0000000</p>
    <p>最小的正整数 1                 计算机中二进制标示: 00000000 00000001</p>
    <p>最大的正整数:32767    计算机中二进制标示: 01111111  11111111</p>

    最小负整数-32768加1之后,在计算机中的表示就是:10000000 00000001,对应的值就是- (2^{15} -1),即-32767。然后一直加1,直到11111111 11111111,对应的值就是-1,再加1,就变成了1 00000000 00000000,即17位,而short类型只读取16位,所以-1+1=0。00000000 00000000一直加1,加到01111111 11111111,就变成了short类型的最大整数32767。再加1,就变成了10000000 00000000,即最小负数:-32768。对应的循环图如下:

    short_int.png

    理解了这些之后就不难明白,为什么上一段程序的运行结果是0了。平时还是要多温故基础知识,否则很可能在一些不起眼的地方栽了坑。

    参考资料

    谈谈Java中整数类型(short int long)的存储方式

    相关文章

      网友评论

        本文标题:Java int 类型数值越界引发的思考

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