二进制位的原码反码补码转换 以及 按位与&、按位或|、异或^
- 一、二进制位的原码、反码、补码转换
- 1.机器数
- 2.原码
- 3.反码
- 4.补码
- 二、按位与&、按位或|、异或^
最近在练习LeetCode上的算法题,遇到了位运算求解的问题,作以复习总结。
一、二进制位的原码、反码、补码转换
在计算机当中都是使用补码来进行计算和存储的。反码解决了正确计算负数问题;
补码很好的解决了反码 负数不能跨零计算的弊端;
并且补码还可以记录一个特殊的值 -128,这个数据在 1 个字节下是没有原码和反码。
正数的原码反码补码相同;
负数的原码—>反码: 符号位不变,其余各位取反;
负数的反码—>补码: 反码加上1(相当于将原码数值位取反然后在最低位加1) ;
1.机器数
机器数:一个数在计算机中的表示形式是二进制;
机器数通常是带有符号的(指有正数和负数之分),计算机用最高位存放符号,这个 bit 一般叫做符号位。 正数的符号位为 0, 负数的符号位为 1。
比如,十进制中的数 +7 ,计算机字长为8位,转换成二进制就是 0 0 0 0 0 1 1 1(一个 byte 有 8bit,有效的取值范围是 -128 ~ +127)。如果是 -7 ,就是1 0 0 0 0 1 1 1。
计算机底层使用二进制形式的补码来计算和存储数据
一个存储的二进制码分原码、反码、补码!
2.原码
十进制数据的二进制表现形式就是原码,原码最左边的一个数字就是符号位,0为正,1为负。
左边第一位为符号位,其他位为数据位。
一个 byte 有 8bit,最大值是 0 1 1 1 1 1 1 1(+127),最小值是 1 1 1 1 1 1 1 1(-127)
在计算机中之所以使用二进制来表示原码是因为逻辑简单,对于电路来说只有开或者关两种状态,用二进制是在方便不过的了。
计算:
使用原码对正数进行计算不会有任何问题的。
但是如果是负数的话,那计算的结果就会大相径庭了。
例如 :5+20 0 0 0 0 1 0 1+ 0 0 1 0-----------------0 0 0 0 0 1 1 1
结果没问题,值为7.如果是负数,-56 -11 0 1 1 1 0 0 0- 1-----------------1 0 1 1 0 1 1 1
显然结果不应该是-55!减一之后正确的结果应该是 -57(1 0 1 1 1 0 0 1)才对。
为了解决原码不能用于计算负数的这种问题,这时候,反码它出现了,作为负数的“计算的救星”。
计算规则是正数的反码不变和原码一致,负数的反码会在原码的基础上,高位的符号位不变,其他位取反( 1 变成 0 , 0 变为 1 )。
3.反码
正数的反码是其本身(等于原码),负数的反码是符号位保持不变,其余位取反。反码的存在是为了正确计算负数,因为原码不能用于计算负数。
十进制数字 | 原码 | 反码 |
---|---|---|
+0 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 |
-1 | 1000 0001 | 1111 1110 |
负数计算
这时候,我们再来使用反码计算一下 -56 - 1 的结果。
-56 的原码是1 0 1 1 1 0 0 0
,如果转成反码(符号位不变,其他位取反)
那么它的反码就是1 1 0 0 0 1 1 1
1 1 0 0 0 1 1 1- 1
-----------------1 1 0 0 0 1 1 0-56 -1 = -57,-57 的原码是1 0 1 1 1 0 0 1,转成反码刚好是1 1 0 0 0 1 1 0,刚好等于刚才我们算出的值。
跨零计算
不过反码也有它的 “ 软肋 ”,如果是负数跨零进行计算的话,计算得出的结果不对.
-3 + 5 来举例
-3 的原码是1 0 0 0 0 0 1 1
,转成反码的话就是 1 1 1 1 1 1 0 0
1 1 1 1 1 1 0 0
+ 0 1 0 1
-----------------0 0 0 0 0 0 0 1
把计算结果转成十进制就是 1,这结果显然不对。那么我们该怎么计算呢,这时候,作为反码的补充编码 —— 补码就出现了。
作为反码的补充编码 —— 补码就出现了。
4.补码
正数的补码是其本身,负数的补码等于其反码 +1。因为反码不能解决负数跨零(类似于 -6 + 7)的问题,所以补码出现了。
跨零计算
这时候,我们再来使用反码计算一下 -3 + 5 的结果。
-3 的原码是1 0 0 0 0 0 1 1
,转成反码的话就是 1 1 1 1 1 1 0 0
,再转成补码就是1 1 1 1 1 1 0 1
。
1 1 1 1 1 1 0 1
+ 0 1 0 1
----------------- 0 0 0 0 0 0 1 0
结果正确。
二、按位与&、按位或|、异或^
运算符 | 含义 | 运算规则 | 用途 |
---|---|---|---|
& | 位与 | 两个位都是1,结果为1,其他为0 | 1.判断奇偶数:用if ((a & 1) == 0) 代替 if (a % 2 == 0)来判断a是不是偶数;2.取余:让a对16进行取余,那么就可以让 a & 15 |
| | 位或 | 两个位都是0,结果为0,其他为1 | |
^ | 位异或 | 同0异1:相同为0,不同为1 | 交换两个数:(a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a,a^0=a |
~ | 位非 | 0变1,1变0 | 求相反数: ~a + 1 |
<< | 左移 | 向左移动,低位补零 | 做 * (2 ^ n)的运算 |
>> | 右移 | 向右移动,高位补零,符号位按照原来数字的符号位不变 | 1.做 / (2 ^ n)的运算;2.求绝对值: a >> 31 == 0 ? a : (~a + 1) |
>>> | 无符号右移 | 向右移动,高位补零 | - |
下一篇有关于位运算实际使用的介绍!