如何判断2的n次方?用四种方式来扒一扒。

写在前面:

      关于求2的n次方问题一直是一个比较基础,但是常常拿来考察的问题,下面我列举了4种方法来判断2的n次幂,并简单测一下各种方法的效率。今天咱们就来好好扒一扒这2的n次方判断问题。

方式一:用while循环反复除

这种方式肯定是最好想到的,反复除,判断余数是否为零。

    public static boolean check2(int x) {
        if (x < 1) {
            return false;
        }
        int xx = x;//定义xx保存x的值,后面用来判断余数是否为零
        while (x >= 2) {
            xx = x;
            x = x / 2;
            if (xx - x * 2 != 0) {
                return false;
            }
        }
        return true;
    }

方式二:用while循环反复乘

反复乘,大了返回false,小了继续乘,等于就true。

   public static boolean check3(int x) {
        int flag = 1;//被乘的初始值设置为1
        while (true) {
            if (flag < x) {//小了继续乘
                flag *= 2;
            } else if (flag == x) {//等于就true
                return true;
            } else {//大了返回false
                return false;
            }
        }
    }

方式三:(x != 0) && ((x & -x) == x);

原码,反码,补码。

      首先我们要了解一下什么是原码,反码,补码。
      打个比方,拿8来说,求一下他的4位二进制
在这里插入图片描述

      原码:正数符号位为0,数值化为2进制

      反码:符号位不变,数值位取反

      补码:原码符号位置不变,数值位取反末位加一或者是反码直接末位加一(电脑中的数值运算都是用补码表示)

了解了这些,我们可以看一下这段代码(x != 0) && ((x & -x) == x);是什么含义

a.首先我们判断x是否为0,为0直接返回false
  public static boolean check1(int x) {
        return (x != 0) && ((x & -x) == x);
  }
b.我们还是拿8来说

在这里插入图片描述

      我们可以看到8的补码和-8的补码进行&运算(同一为一),得到的结果刚好就是8的本身。即(x & -x) == x。

      而且我们可以看到,当判断的x为-8时相&的结论是与-8本身不一样的,这就很好的减少了我们判断负数的工作

c.拿7看就不成立了

在这里插入图片描述

方式四:((x != 0) && ((x & x - 1) == 0));

       这个和上面的方式异曲同工

在这里插入图片描述

测试效率

 public static void main(String[] args) {
        long timeA1 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            if (check2(i)) {
                System.out.print(i);
            }
        }
        long timeA2 = System.currentTimeMillis();
        System.out.println("方式一:" + (timeA2 - timeA1));

        long timeB1 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            if (check3(i)) {
                System.out.print(i);
            }
        }
        long timeB2 = System.currentTimeMillis();
        System.out.println("方式二:" + (timeB2 - timeB1));

        long timeC1 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            if (check1(i)) {
                System.out.print(i);
            }
        }
        long timeC2 = System.currentTimeMillis();
        System.out.println("方式三:" + (timeC2 - timeC1));


        long timeD1 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            if (check11(i)) {
                System.out.print(i);
            }
        }
        long timeD2 = System.currentTimeMillis();
        System.out.println("方式四:" + (timeD2 - timeD1));
    }

在这里插入图片描述

基本上来说方式三,四的执行效率差不多,大约都是方式一的三到四倍,方式二的七到八倍。

我最想说的是(等下我是不是跑题了,滑稽.jpg)

      在计算机的设计中是只有加法器没有减法器的,因为其实减法都是可以用加法来实现的,如同7-3=4可以写成7+(-3)=4,这就减少了计算机还要设计减法器的麻烦。而为了计算机实现的简便,就出现了补码的概念。举个例子

在这里插入图片描述

可以看到使用补码相加直接得到了0 0100,转换成十进制就是4,对计算机来说这就很方便了,减少了设计减法器,感觉干掉了一半的工作量。

总结:

      要是再次面对这个问题时,可以和面试官含情脉脉娓娓道来,一个2的n次方聊上十几二十分钟也不是不可以!滑稽.jpg。毕竟基础的东西还是很重要的,这种问题往往能反映出一个人的基础是否扎实

如果喜欢或者对你有帮助,老铁记得点个赞哦。
在这里插入图片描述

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值