Java 数值的二进制中1的个数和整数次方

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lilong117194/article/details/83957738

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} ,13表达为二进制是1101,即 2. 0 1101 2.0^{1101} 。而$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}。
这里主要是通过&1和>>1来逐位读取1101:

  • 首先1101&0001=0001,即读取到1101的最低位,最低位对应的是 2 0 2^0 ,此时总值为sum= 2. 0 2 0 2.0^{2^0}
  • 通过1101右移得到0110,再&1运算,得到是0,即该位没有数字1,但是该位对应的是 2 1 2^1 ,并不计入总值。
  • 通过0110右移得到0011,再&1运算,得到1,该位对应的是 2 2 2^2 ,计入总值为
    sum= 2. 0 2 0 + 2. 0 2 2 2.0^{2^0}+2.0^{2^2}
  • 通过0011右移得到0001,再&1运算,得到1,该位对应的是 2 3 2^3 ,计入总值为
    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}

所以最终的迭代结果是: s u m = 2. 0 1 + 4 + 8 = 2. 0 13 sum=2.0^{1+4+8}=2.0^{13}

还有就是边界条件的限制:要注意指数为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

以上仅作为学习笔记。。

猜你喜欢

转载自blog.csdn.net/lilong117194/article/details/83957738