目录:
[图片上传失败…(image-98c3f8-1616855044646)]
要求十进制转二进制,首先我们想到的是除2求余法,比如数字15,如下,不断的除以2,一直到0为止,最后将余数倒序排列就是该数的二进制表示
15/2 = 7 --------余1
7/2 = 3 --------余1
3/2 = 1 --------余1
1/2 = 0 --------余1
所以15的二进制表示就是1111,再举一例,520的二进制表示
520/2 = 260 -------余0
260/2 = 130 -------余0
130/2 = 65 --------余0
65/2 = 32 --------余1
32/2 = 16 --------余0
16/2 = 8 --------余0
8/2 = 4 --------余0
4/2 = 2 --------余0
2/2 = 1 --------余0
1/2 = 0 --------余1
余数倒序排列就是1000001000,所以520的二进制表示就是1000001000,那么把上述的算法用作代码写出来是怎么样的呢?
第一个版本
Java代码将上述过程表达出来如下
public static String toBinary(int i){
StringBuilder sb = new StringBuilder();
while (i > 0){
//i%2求余 比如15%2=1
sb.append(i % 2);
//求余之后除以2再赋值给i
//注意,i是整型,所以小数会抹去,比如15/2=7,而不是7.5
i = i / 2;
}
//将最后的结果逆序后再返回
return sb.reverse().toString();
}
验证一下
System.out.println(toBinary(520));//我们自己写的
System.out.println(Integer.toBinaryString(520));//JDK自带的
看看结果,输出是一样的说明验证通过
1000001000
1000001000
但是对于追求极致性能的我们来说并不满足上面的转换,因为求余操作符%的性能并没有位运算高,所以我们改成位运算,所以就出现了下面的第二个版本
第二个版本
第二个版本主要引入位运算为后面JDK的实现做好基础。
public static String toBinary1(int i){
StringBuilder sb = new StringBuilder();
while (i > 0){
//任何数与1做与运算,
// 结果是0说明是偶数,任何偶数与2相除都余0
// 结果是1说明是奇数,任何奇数与2相除都余1
sb.append(i & 1);
//求余之后除以2再赋值给i,i >> 1 表示 i / 2^1,
//注意,i是整型,所以小数会抹去,比如15/2=7,而不是7.5
i = i >> 1;//也可以写成 i >>= 1
}
return sb.reverse().toString();
}
重点说明i & 1
我们知道 i % 2 是除以2后的求余操作,比如 15 % 2 = 1 ,那么i & 1运算又是什么鬼?从上文可知,那么我们来证明下面的公式
i % 2 = i & 1
对不熟悉位运算的同学可能一头雾水,这都是些啥符号,&表示二进制与运算,运算法则为全1得1,有0得0,举个例子
# 15 的二进制位1111 , 1的二进制位0001
15 & 1 = 1111 & 0001 = 1
i & 1只能说明奇偶性,只看i的最后一位,如果最后一位是1说明是奇数,是0说明是偶数,这个怎么证明?先看二进制量表,所有的整数都可以从量表中的数字加起来表示,比如15 = 8+4+2+1,每位上都有,所以15的二进制是1111,二进制就是这么神奇,无论什么整数你都可以从下面的量表中找出数字加起来表示
[图片上传失败…(image-c413a8-1616855044646)]
扯远了,回来看一下量表,只有最低位2^0=1这个数字是奇数是吧,其他所有的数字全都是偶数,那么偶数加偶数还是偶数,偶数加1就是奇数,奇数加1?根本不存在这种情况,因为只有一个1,偶数变成奇数已经用掉了,比如3 = 2 + 1 = 011 (二进制) ,4 = 4 &#