Java 二进制
计算机只有1和0,这就是二进制
我们平常看到的10,20等等都是十进制,是由二进制转换过来的
1.二进制 八进制 十六进制转换
下面的例子带你从十进制转换成二进制,八进制和十六进制
int a =11;
//Integer.toBinaryString( )的返回值是String类型
System.out.println(Integer.toBinaryString( a));//十进制转换成二进制 输出是:1011
System.out.println(Integer.toOctalString(a));//十进制转换成八进制 输出是:13
System.out.println(Integer.toHexString(a));//十进制转换成十六进制 输出是:b
//大家注意在16进制中10是a,11是b,12是c,13是d,14是e,15是f
- 一般来说1个字节是8位,在案例中int类型是32位,所以正常输出是32位,但是你只能看到4位1011->8+2+1=11,是因为前面有28个0,为了方便就去掉了
- 8位输出的是13代表着1*8+3=11
二进制,十六进制赋值
//二进制
int binary = 0b11;
//十六进制
int hex = 0xff;
2.补码
那么有些同学可能在想有正数和负数,负数一般怎么表示。
负数是整型的第一位是1
例如int是32位,
- 第一位是1代表这个数是负数,不加入计算,注意计算的时候必须要加-1
- 1111 1111 1111 1111 1111 1111 1111 1111代表着-1
- 1111 1111 1111 1111 1111 1111 1111 1110代表着-2=-1-(1)
- 1111 1111 1111 1111 1111 1111 1111 1101代表着-3=-1-(2)
- 1111 1111 1111 1111 1111 1111 1111 1100代表着-4=-1-(2+1)
- 1111 1111 1111 1111 1111 1111 1111 1011代表着-5=-1-(4)
- 等等
下面是一个例子:
System.out.println(Integer.toBinaryString(-22));
//输出是11111111111111111111111111101010=-1-(1+4+16)=-22
// 00000000000000000000000000010101
那什么是补码,假如一个二进制的数是1101很明显这是一个负数是-3,那么他的补码就是 3,但是1101反过来应该是0010=2,少了个1,所以补码的规则是 -n=~n+1
例子:
int a =-5;
System.out.println(Integer.toBinaryString(a));
//a的补码是-1 输出为101
System.out.println(Integer.toBinaryString(-a));
//我们用补码规则做~n+1 输出为101
System.out.println(Integer.toBinaryString(~a+1));
3.二进制运算
运算符号 | 运算规则 |
---|---|
~ | 取反 |
& | 与运算 |
| | 或运算 |
>>> | 右位移运算 |
>> | 数学右位移运算 |
<< | 左位移运算 |
取反: ~
例子: 1101 取反就是0010
与运算: &
只有运算两边都是1输出才是1,01,10,00输出都是0
输入 | 输入 | 输出 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
例子:
/* 1100
& 0101
输出: 0100 */
Byte demo = 0b1100 & 0b0101;
System.out.println(Integer.toBinaryString(demo));//输出是0100
或运算: |
或运算除了00是0,其他都为1
输入 | 输入 | 输出 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
例子:
/* 1100
& 0101
输出: 1101 */
Byte demo = 0b1100 | 0b0101;
System.out.println(Integer.toBinaryString(demo));//输出是1101
右位移运算: >>>
>>> 逻辑右移位:数字向右移动,低位自动溢出,高位补0, 结果没有数学意义
例子:
int a = 0x2222;
System.out.println(Integer.toBinaryString(a)); //10001000100010
System.out.println(Integer.toBinaryString(a>>>1));//1000100010001
上个例子可以很清晰的看到向右移了一位,最后一个0就删除了
左移位运算: <<
2进制数字整体向左移动,高位自动溢出,低位补0
数学意义就是向左移一格就是乘2,移两格就是乘两个2,移三格就是乘3个2
int a = 0b10;
System.out.println(Integer.toBinaryString(a)); //输出:10 =2
System.out.println(Integer.toBinaryString(a<<1)); //输出:100 =4
System.out.println(Integer.toBinaryString(a<<2)); //输出:1000 =8
原因在于向右移,就是把2的移到4的位置去,所以数学意义是移一格乘2
右移位运算:>>
数学右移位:数学向右移动,低位自动溢出,正数高位补0,负数高位补1, 移动一次数学除以2,小方向取整数。如果是替代数学 /2, 使用数学右移位
int a = 0b1000;
System.out.println(Integer.toBinaryString(a)); //输出: 1000 =8
System.out.println(Integer.toBinaryString(a>>1)); //输出: 100 =4
System.out.println(Integer.toBinaryString(a>>2)); //输出: 10 =2
扩展
将一个32位int分成4个字节,再合并
思路:
- 分成4个字节:先与运算再向右移
- 合并:4个字节左移位再或运算
//分开整数
int a = 0x12345678;//原整数
//先与运算,再向右移动24,让0x12到达最右边
int a1 = (a & 0xff000000) >>> 24;
//先与运算,再向右移动16,让0x34到达最右边;先右移位再右运算也是一样的结果
int a2 = (a & 0xff0000) >>> 16;
//先与运算,再向右移动8,让0x56到达最右边
int a3 = (a & 0xff00) >>> 8;
//0x78本身就在最右边,直接与运算就行
int a4 = a & 0xff;
//a输出是:10010001101000101011001111000
System.out.println(Integer.toBinaryString(a));
System.out.println(Integer.toBinaryString(a1));//输出是:0001,0010 =12
System.out.println(Integer.toBinaryString(a2));//输出是:0011,0100 =34
System.out.println(Integer.toBinaryString(a3));//输出是:0101,0110 =56
System.out.println(Integer.toBinaryString(a4));//输出是:0111,1000 =78
//合并整数
int aNew = (a1<<24) | (a2<<16) | (a3<<8) | a4;
//aNew输出是:10010001101000101011001111000
System.out.println(Integer.toBinaryString(aNew));