1. 数值的二进制中1的个数
1.1 题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
1.2 解题思路
思路一:直接使用java自带的函数Integer.toBinaryString().toCharArray();
把整数转换成二进制后再以字符串表示。
思路二:
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。(参考一大神)
总结以下就是:先减去1,然后原数和减去后的数做与,计算做与的操作次数。这样做的原因:每一个二进制数是由0、1组成,减去1就是把原数的最右边位的1变为0,再与运算就是看与操作后还有几个1,所以最后操作几次与运算就有几个1。
1.3 代码
思路一:
public class NumberOfBinary {
public static void main(String[] args){
NumberOfBinary mm=new NumberOfBinary();
int t1=mm.NumberOf1(5);
System.out.println(t1);
int t2=mm.NumberOf1(-5);
System.out.println(t2);
}
public int NumberOf1(int n){
int t=0;
char[] ch=Integer.toBinaryString(n).toCharArray();
for(int i=0;i<ch.length;i++){
if(ch[i]=='1'){
t++;
}
}
return t;
}
}
运行:
2
31
思路二:
public class NumberOfBinary {
public static void main(String[] args){
NumberOfBinary mm=new NumberOfBinary();
int t1=mm.NumberOf1(5);
System.out.println(t1);
int t2=mm.NumberOf1(-5);
System.out.println(t2);
}
public int NumberOf1(int n){
int count = 0;
while(n!= 0){
count++;
n = n & (n - 1);
}
return count;
}
}
运行:
2
31
2. 数值的整数次方
2.1题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
2.2 解题思路
这里采用的是快速幂方法:
例如求
2.
0
13
2.0^{13}
2.013,13表达为二进制是1101,即
2.
0
1101
2.0^{1101}
2.01101。而$2.0^{1101}的组成
2.
0
1101
=
2.
0
0001
∗
2.
0
0100
∗
2.
0
1000
。
2.0^{1101} = 2.0^{0001}*2.0^{0100}*2.0^{1000}。
2.01101=2.00001∗2.00100∗2.01000。
这里主要是通过&1和>>1来逐位读取1101:
- 首先1101&0001=0001,即读取到1101的最低位,最低位对应的是 2 0 2^0 20,此时总值为sum= 2. 0 2 0 2.0^{2^0} 2.020
- 通过1101右移得到0110,再&1运算,得到是0,即该位没有数字1,但是该位对应的是 2 1 2^1 21,并不计入总值。
- 通过0110右移得到0011,再&1运算,得到1,该位对应的是
2
2
2^2
22,计入总值为
sum= 2. 0 2 0 + 2. 0 2 2 2.0^{2^0}+2.0^{2^2} 2.020+2.022 - 通过0011右移得到0001,再&1运算,得到1,该位对应的是
2
3
2^3
23,计入总值为
sum= 2. 0 2 0 + 2. 0 2 2 + 2. 0 2 3 2.0^{2^0}+2.0^{2^2}+2.0^{2^3} 2.020+2.022+2.023
所以最终的迭代结果是: s u m = 2. 0 1 + 4 + 8 = 2. 0 13 sum=2.0^{1+4+8}=2.0^{13} sum=2.01+4+8=2.013
还有就是边界条件的限制:要注意指数为0和底为0的各种情况。
2.3 代码
public class NumIntegerPower {
public static void main(String[] args){
NumIntegerPower mm=new NumIntegerPower();
double tt=mm.power(2.0,4);
System.out.println(tt);
}
public double power(double base, int n) {
double res = 1,curr = base;
int exponent;
if(n>0){ // 指数为正时
exponent = n;
}else if(n<0){ // 指数为负时
if(base==0)
throw new RuntimeException("分母不能为0");
exponent = -n;
}else{ // n==0
return 1;
}
while(exponent!=0){
if((exponent&1)==1) // 幂次是否有该位
res*=curr;
curr*=curr; //
exponent>>=1;// 右移一位,n >>= 1 等价于 n /= 2
}
return n>=0?res:(1/res);
}
}
运行:
16.0
以上仅作为学习笔记。。