注:部分网上查找的资料,如有侵权,请联系我删除!
最近遇到了一个问题:一个十进制数解析成5位的2进制数,每位代表一个参数。简单记录下解决的方法和过程中学到的东西。
一、进制转换问题
1)除2取余倒转
对于十进制转二进制,首先想到的就是”除2取余倒转”这种方法。稍微要注意的就是它是从低位开始,记得要倒转。
private void decimalToBinary(int n) {
StringBuilder binary = new StringBuilder();
while (n != 0) {
//因为是从低位开始的,所以使用insert方法,将字符拼接到原字符前面
binary.insert(0, n % 2);
n /= 2;
}
System.out.println(“binary=”+binary.toString());
}
2) API
在Integer里面有个toBinaryString(int i)方法,可以将十进制数位转化为二进制。这是最简单的方法
private void decimalToBinary(int n) {
System.out.println(“binary=”+Integer.toBinaryString(n));
}
3)移位运算
我们都知道,所有的数都是以二进制存储的,当我们将二进制数右移它的 (本身长度-1) 位,得到的就是它的最高位的值;
如果是右移 (长度-2)位,那么得到的就是最高两位。但是我们只需要第二位,如何去掉最高位呢?因为在二进制中只有0和1两位数,这两个数&1得到的还是它本身。利用这个特性,我们可以将最高两位 &1,这样就可以消掉最高位而得到第二位。
private void decimalToBinary(int num, int size) {
StringBuilder binStr = new StringBuilder();
for(int i = size-1;i >= 0; i–){
binStr.append(num >>> i & 1);
}
System.out.println(“binStr=”+binStr.toString());
}
这里上面代码是有问题的,就是如果传入的数二进制有5位,但是size却是3位,它就会从低位开始到size位数作为结果,这样得到的结果是错误的。所以加一个判断传入的size是否满足要转化的值位数。还是Integer,它里面有个numberOfLeadingZeros(int i)方法,这个方法就是计算在int数值前面加0个数,使添加0之后的数(二进制)是32位。
注:numberOfLeadingZeros(int i)这个方法的实现非常巧妙!!
添加size判断代码
private void decimalToBinary(int num,int size){
if (size <(Integer.SIZE – Integer.numberOfLeadingZeros(num))) {
throw new RuntimeException(“传入size小于num二进制位数”);
}
StringBuilder binStr = new StringBuilder();
for(int i = size-1;i >= 0; i–){
binStr.append(num >>> i & 1);
}
System.out.println(“binStr=”+binStr.toString());
}
二、Java移位运算
在解决这个问题的时候,碰到了Java移位运算,这里写一点简单的理解:
前提:在不考虑 数值符号 和 数值范围 的情况下(正数),
可以简单地认为:左移就是乘于2的n次方,右移就是除以2的n次方,注意 int 的除法;
x >> n ==> x/ 2^n
x << n ==> x* 2^n
也可以这样认为 把 十进制数 换成二进制,左移就在二进制数的后面补0,右移就在数的前面补n个0(并划掉最后的n位),再转化成十进制数。例如 5对应二进制位 101
右移: 5 >> 2 ==> 101 >> 2 => 00101(前面补2个零,并划掉最后2位)=001=1 ==> 5>>2=1;
左移: 5 << 2 ==> 101 << 2 => 10100 = 20 ==> 5<<2 = 20)