zoukankan      html  css  js  c++  java
  • java中int算法的有趣现象

    今天无意中发现一个怪事,当时没理解,后来跟网友讨论了才知道原理,是关于int值的加法算法,两段代码如下:

    代码1:

        @Test
        public void test1() {
            int stackLength = 1;
            int count = 0;
            try {
                while(true){
                    count++;
                    stackLength += stackLength; //每次打印的值为0
                    System.out.println("stackLength="+count+"次:: "+stackLength);
                }
            } catch (Exception e) {
                System.out.println("occur exception!!! stackLength="+stackLength);
            }
        }

    控制台输出结果很奇怪,全都是0,:

    stackLength=21719次:: 0
    stackLength=21720次:: 0
    stackLength=21721次:: 0
    stackLength=21722次:: 0
    stackLength=21723次:: 0
    stackLength=21724次:: 0
    stackLength=21725次:: 0

    ……  由于打印太快,已经计算了2万多次。

    代码2:

        @Test
        public void test2() {
            int stackLength = 1;
            int count = 0;
            try {
                while(true){
                    count++;
                    stackLength += 1;
                    System.out.println("stackLength="+count+"次:: "+stackLength);
                }
            } catch (Exception e) {
                System.out.println("occur exception!!! stackLength="+stackLength);
            }
        }

    控制台打印结果正常,是一个数一个数加上去的:

    stackLength=21211次:: 21212
    stackLength=21212次:: 21213
    stackLength=21213次:: 21214
    stackLength=21214次:: 21215
    stackLength=21215次:: 21216
    stackLength=21216次:: 21217
    stackLength=21217次:: 21218
    stackLength=21218次:: 21219
    stackLength=21219次:: 21220
    stackLength=21220次:: 21221
    stackLength=21221次:: 21222
    stackLength=21222次:: 21223

    ……

    思路

    这就很奇怪了,代码1和代码2中,只有一行代码不一样,

    在代码1中为stackLength += stackLength;

    在代码2中为stackLength += 1;

    但是运行2万多次后,结果却大相径庭。后来与网友讨论才明白其中原理如下:

    先说  i+=i 吧,二进制运算的知识。
    初始值1  就是 0000 0000 0000 0000 0000 0000 0000 0001 ,
    加自己就是  0000 0000 0000 0000 0000 0000 0000 0010.
     0000 0000 0000 0000 0000 0000 0000 0010 + 0000 0000 0000 0000 0000 0000 0000 0010 就=2+2  
    结果就是 0000 0000 0000 0000 0000 0000 0000 0100 也就是4
    一直到31次的时候,
    就变成  1000 0000 0000 0000 0000 0000 0000 0000 
    这个值是最小负数
    因为 int是32位。当最高符号位超出32位,最后两个最大的负数相加的时候,符号位也变成0了,后32位都是0,就是32个0,所以后面就一直是0了。
    当是33位时,两个最大负数相加,连33位都变成了0
    因为int只能取32位
    所以就是0
    然后后面就一直是0+0了
     
    好了,明白了这个道理,我们来看看是不是这样的,首先把源码改成如下:
    例子3:
        @Test
        public void test3() {
            int stackLength = 1;
            int count = 0;
            try {
                while(true){
                    count++;
                    stackLength += stackLength;
                    System.out.println("stackLength="+count+"次:: "+stackLength);
                    if(count > 40){
                        break;
                    }
                }
            } catch (Exception e) {
                System.out.println("occur exception!!! stackLength="+stackLength);
            }
        }

    控制台打印如预期之中:

    stackLength=1次:: 2
    stackLength=2次:: 4
    stackLength=3次:: 8
    stackLength=4次:: 16
    stackLength=5次:: 32
    stackLength=6次:: 64
    stackLength=7次:: 128
    stackLength=8次:: 256
    stackLength=9次:: 512
    stackLength=10次:: 1024
    stackLength=11次:: 2048
    stackLength=12次:: 4096
    stackLength=13次:: 8192
    stackLength=14次:: 16384
    stackLength=15次:: 32768
    stackLength=16次:: 65536
    stackLength=17次:: 131072
    stackLength=18次:: 262144
    stackLength=19次:: 524288
    stackLength=20次:: 1048576
    stackLength=21次:: 2097152
    stackLength=22次:: 4194304
    stackLength=23次:: 8388608
    stackLength=24次:: 16777216
    stackLength=25次:: 33554432
    stackLength=26次:: 67108864
    stackLength=27次:: 134217728
    stackLength=28次:: 268435456
    stackLength=29次:: 536870912
    stackLength=30次:: 1073741824
    stackLength=31次:: -2147483648
    stackLength=32次:: 0
    stackLength=33次:: 0
    stackLength=34次:: 0
    stackLength=35次:: 0
    stackLength=36次:: 0
    stackLength=37次:: 0
    stackLength=38次:: 0
    stackLength=39次:: 0
    stackLength=40次:: 0
    stackLength=41次:: 0

    支付宝扫一扫,为女程序员打赏!
    作者:梦幻朵颜
    版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    33 函数参数的传递方式
    33 函数递归调用
    32 头文件
    31 函数
    30 枚举
    centos6.5升级默认的Mysql到5.5方法
    Centos6.5命令行快捷键
    redhat 安装lamp
    CentOS6.5中的vsftpd安装配置
    添加一个用户并且让用户获得root权限
  • 原文地址:https://www.cnblogs.com/zhuwenjoyce/p/6537928.html
Copyright © 2011-2022 走看看