文章目录
写在前面:
关于求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。毕竟基础的东西还是很重要的,这种问题往往能反映出一个人的基础是否扎实。
如果喜欢或者对你有帮助,老铁记得点个赞哦。