不同的算法对同一道题的用时影响?

我的疑问:1.我的代码是否有错误,2,两种方法究竟哪种快,为什么,因为什么底层逻辑还是原理之类的?

原题是这样的:给出任意一个int 类型的正整数,如何快速判断该整数的值,是否是2的整数次幂?

这是第一种方法 //scanner为要求的那个任意数

img

这是第二种

img

我突发奇想,两种方法那种快,第一种是同学写的,第二种是我的。
于是我想验证,首先把输出注释了,因为我的理解,每次反正是最终结果得到的时候输出,用时应该都一样的。
首先第一种验证是,让两种方法对同一个数重复执行,例如执行百万次,然后执行100轮。计算每一轮的用时差距,结果是,第二种的用时普遍远远少于第一种。
后来我想换一种,不让他们对同一个数反复执行,而是对同一堆数反复执行。例如,先生成百万个随机数存到一个数组里,然后每个方法分别对这百万的数进行计算,统计用时,这样也执行100轮。结果是,两种方法各有千秋,但是,第二种都是几十毫秒,但第一种竟然会出现0,差不多是反过来的情况了。
实在搞不懂为什么差距会这么大,我待会展示我的源码给各位大 佬看看,不排除第二次测试的时候,代码写错了,以我的能力,我检不出来错误。如果有错误请各位大 佬指正下,回归主题,我就想知道这两种哪种快,因为什么原理?

第一次测试

long[] A=new long[100];//程序1的
        long[] B=new long[100];
        for(int a=0;a<100;a++){
            int scanner = (int)(Math.random()*1000000000+1);
            System.out.print(scanner+"\t");
            //程序1
            long startTime1=System.currentTimeMillis();//保存开始时间节点
            for(int i=0;i<1000000;i++)//执行一次的用时都是0毫秒,无法比较,都扩大百万倍,比较用时
            {
                int sum=1;
                for(int j=1;j<=30;j++){
                    sum*=2;
                    if(scanner==sum){
                        //System.out.println(scanner+"是2的整数次幂");
                        break;
                    }
                    if(j==30){
                        //System.out.println(scanner+"不是2的整数次幂");
                    }
                }
            }
            long endTime1=System.currentTimeMillis();//保存结束时间节点

            //程序2
            long startTime2=System.currentTimeMillis();
            for (int i=0;i<1000000;i++)
            {
                int num=scanner;
                while(num>1){
                    if(num%2==1){//判断是否是单数,单数没有在计算的必要了,肯定不是2的倍数
                        break;
                    }
                    num=num/2;//让输入的数砍半,如果目标数符合,那重复执行到最后的结果是1,2/2==1
                }
                if(num==1){
                    //System.out.println(scanner+"是2的整数次幂");
                }else {
                    //System.out.println(scanner+"不是2的整数次幂");
                }
            }
            long endTime2=System.currentTimeMillis();

            //最终比较用时
            long time1=endTime1-startTime1;
            long time2=endTime2-startTime2;
            A[a]=time1;B[a]=time2;
            System.out.println("程序1用时"+(time1)+"毫秒,程序2用时"+(time2)+"毫秒");
        }

        long[] difference=new long[100];
        double[] multiple=new double[100];
        long maxDif=Long.MIN_VALUE,minDif=Long.MAX_VALUE;
        double maxMu=Double.MIN_VALUE,minMu=Double.MAX_VALUE;
        for(int i=0;i<100;i++){
            long num1=A[i]-B[i];
            double num2=(double) A[i]/B[i];
            difference[i]=num1;
            multiple[i]=num2;

            if(num1>maxDif){
                maxDif=num1;
            }
            if(num1<minDif){
                minDif=num1;
            }
            if(num2>maxMu){
                maxMu=num2;
            }
            if(num2<minMu){
                minMu=num2;
            }
        }
        System.out.println("两个程序都执行百万次,随机数执行一百轮,第一行为每次两者的时间差,第二行为两者的时间倍数");
        System.out.println(Arrays.toString(difference));
        System.out.println(Arrays.toString(multiple));
        System.out.println("其中最大差值达到了"+maxDif+"\t最小差值有"+minDif);
        System.out.println("其中最大倍数达到了"+maxMu+"\t最小倍数有"+minMu);

第二次测试

int userScan=10;//大循环,决定进行多少轮
        int count=10000000;//小循环,决定多少个随机数数字。使用随机数字,并且让一种算法一次性计算完这些,是为了差距更明显,同时避免程序2出现0时间可能
        long[] A=new long[userScan];//程序1的
        double[] B=new double[userScan];
        for(int big=0;big<userScan;big++)
        {
            int[] random=new int[count];
            //生成count数量的随机数,保存到random数组中
            for(int a=0;a<count;a++){
                random[a]=(int)(Math.random()*1000000000+1);//范围为十亿
            }

            //程序1
            long startTime1=System.currentTimeMillis();//保存开始时间节点
            for(int first=0;first<count;first++) {
                int sum = 1;
                for (int j = 1; j <= 30; j++) {
                    sum *= 2;
                    if (random[first] == sum) {
                        //System.out.println(scanner+"是2的整数次幂");
                        break;
                    }
                    if (j == 30) {
                        //System.out.println(scanner+"不是2的整数次幂");
                    }
                }
            }
            long endTime1=System.currentTimeMillis();//保存结束时间节点

            //程序2
            long startTime2=System.currentTimeMillis();
            for (int first=0;first<count;first++) {
                int num = random[first];
                while (num > 1) {
                    if (num % 2 == 1) {//判断是否是单数,单数没有在计算的必要了,肯定不是2的倍数
                        break;
                    }
                    num = num / 2;//让输入的数砍半,如果目标数符合,那重复执行到最后的结果是1,2/2==1
                }
                if (num == 1) {
                    //System.out.println(scanner+"是2的整数次幂");
                } else {
                    //System.out.println(scanner+"不是2的整数次幂");
                }
            }
            long endTime2=System.currentTimeMillis();

            //最终比较用时
            long time1=endTime1-startTime1;
            long time2=endTime2-startTime2;
            A[big]=time2-time1;
            B[big]=(double)time2/time1;
            System.out.println("程序1用时"+(time1)+"毫秒,程序2用时"+(time2)+"毫秒");
        }

        long maxDif=Long.MIN_VALUE,minDif=Long.MAX_VALUE;
        double maxMu=Double.MIN_VALUE,minMu=Double.MAX_VALUE;
        for(int i=0;i<userScan;i++){
            long num1=A[i];
            double num2=B[i];
            if(num1>maxDif){
                maxDif=num1;
            }
            if(num1<minDif){
                minDif=num1;
            }
            if(num2>maxMu){
                maxMu=num2;
            }
            if(num2<minMu){
                minMu=num2;
            }
        }//遍历AB数组,将差值倍数存入相对应的数组,同时找到最大值最小值

        System.out.println("两个程序都执行"+userScan+"轮,每轮生成"+count+"个随机数,两种算法分别对这相同的随机数进行处理,第一行为每轮两者用时的时间差,第二行为两者的时间倍数");
        System.out.println(Arrays.toString(A));
        System.out.println(Arrays.toString(B));
        System.out.println("其中最大差值达到了"+maxDif+"\t最小差值有"+minDif);
        System.out.println("其中最大倍数达到了"+maxMu+"\t最小倍数有"+minMu);

这是第一种测试的结果,结果很明显第二种方法快很多

img

这第二种测试的结果很明显有问题,但我找不到

img

img

肯定有影响呀,算法的时间复杂度和空间复杂度会影响程序的时间,所以要择优选择算法,或者先解出题目,然后再做优化

这样子测试,实际上还没排除jit的影响。运行jvm的时候把jit关了再测试吧。