嗯,昨天在复习java的时候遇到进制计算和反码补码原码的转换,脑子里没什么印象了,还是好记性不如烂笔头啊~
写在最前面的是几位大佬对这些东西的理解
_天行健反码补码原码原文链接
小猴子monkey1024位运算原文链接
位运算
位运算符:
& 位与
| 位或
^ 位异或
~ 取反
移位运算符:
>> 向右移
>>> 无符号右移
<< 向左移
位运算符都是操作的二进制
用法:
&,|,^,~ 的用法
&:有0则0
|:有1则1
^:相同则0,不同则1
~:按位取反
例子:
System.out.println(6 & 3); //2
System.out.println(6 | 3); //7
System.out.println(6 ^ 3); //5
System.out.println(~6); //-7?
分析:
上面这些运算符会将数字转换成2进制再进行运算。6的二进制是110,3的二进制是011。根据上面的用法规则里面,列几个竖式:
例子1:
110
011
———–
010 &计算出十进制的2
例子2:
110
011
———–
111 |计算出十进制的7
例子3:
110
011
———–
101 ^计算出十进制的5
如果不了解原码反码补码的同学没有关系,这部分作为了解即可
00000000 00000000 00000000 00000110 6的原码反码补码都是本身
11111111 11111111 11111111 11111001 对6取反,得到-7的补码
00000000 00000000 00000000 00000001 补码减1
——————————————————————————
11111111 11111111 11111111 11111000 反码
10000000 00000000 00000000 00000111 原码(-7)
^的特点:一个数据对另一个数据位异或两次,该数本身不变。
例子:
System.out.println(5 ^ 10 ^ 5);
左移和右移
<<:左移 左边最高位丢弃,右边补齐0
>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1
>>>:无符号右移 无论最高位是0还是1,左边补齐0
例子:
//右移,向右移动n位就是除以2的n次幂,向左移动n位就是乘以2的n次幂
System.out.println(12 >> 1);
System.out.println(12 >> 2);
System.out.println(12 << 1); //24
System.out.println(12 << 2); //48
进制运算
进制也就是进制位,对于接触过电脑的人来说应该都不陌生,我们常用的进制包括:二进制、八进制、十进制与十六进制,它们之间区别在于数运算时是逢几进一位。比如二进制是逢2进一位,十进制也就是我们常用的0-9是逢10进一位。
二进制与十进制之间的转换
-
十进制转二进制
方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。
-
二进制转十进制
方法为:把二进制数按权展开、相加即得十进制数。
二进制与八进制之间的转换
-
二进制转八进制
方法为:3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。
八进制转成二进制
方法为:八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。
反码补码原码
二进制与十六进制之间的转换
-
二进制转十六进制
方法为:与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。
-
十六进制转二进制
方法为:十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。
-
十进制与八进制与十六进制之间的转换
十进制转八进制或者十六进制有两种方法
第一:间接法—把十进制转成二进制,然后再由二进制转成八进制或者十六进制。这里不再做图片用法解释。
第二:直接法—把十进制转八进制或者十六进制按照除8或者16取余,直到商为0为止。
-
八进制或者十六进制转成十进制
方法为:把八进制、十六进制数按权展开、相加即得十进制数。
十六进制与八进制之间的转换
八进制与十六进制之间的转换有两种方法
第一种:他们之间的转换可以先转成二进制然后再相互转换。
第二种:他们之间的转换可以先转成十进制然后再相互转换。原码是什么?
原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码
举例说明:
int类型的 3 的原码是 11B(B表示二进制位), 在32位机器上占四个字节,那么高位补零就得:
00000000 00000000 00000000 00000011
int类型的 -3 的绝对值的二进制位就是上面的 11B 展开后高位补零就得:
10000000 00000000 00000000 00000011
但是原码有几个缺点,零分两种 +0 和 -0 。很奇怪是吧!还有,在进行不同符号的加法运算或者同符号的减法运算的时候,不能直接判断出结果的正负。你需要将两个值的绝对值进行比较,然后进行加减操作 ,最后符号位由绝对值大的决定。于是反码就产生了。
-
反码是什么 ?
正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反
举例说明:
int类型的 3 的反码是
00000000 00000000 00000000 00000011
和原码一样没什么可说的
int类型的 -3 的反码是
11111111 11111111 11111111 11111100
除开符号位 所有位 取反
解决了加减运算的问题,但还是有正负零之分,然后就到补码了
- 补码是什么?
正数的补码与原码相同,负数的补码为 其原码除符号位外所有位取反(得到反码了),然后最低位加1.
还是举例说明:
int类型的 3 的补码是:
00000000 00000000 00000000 00000011
int类型的 -3 的补码是
11111111 11111111 1111111 11111101
就是其反码加1
最后总结一下:
1.正数的反码和补码都与原码相同。
2.负数的反码为对该数的原码除符号位外各位取反。
3.负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1
各自的优缺点:
1.原码最好理解了,但是加减法不够方便,还有两个零。
2.反码稍微困难一些,解决了加减法的问题,但还是有有个零。
3.补码理解困难,其他就没什么缺点了