我发现网上关于标题上的内容介绍的都很零碎,因此为了方便查找、也为了本人对这一部分的充分理解,就想着写一篇这样的博客(我分成了几个部分,以便查找):
一、进制转换
让我们先来看看各个进制的定义:
- 十进制:就是我们平时很熟悉的,例如123、52、39等等;
- 二进制:以0b开头(那是零,不是英文o,因为二进制英文是binary,所以是0b),例如:0b11(也就是十进制中的3);
- 八进制:以0开头(零),例如015(也就是十进制的13);
- 十六进制:以0x或0X开头(零、英文x或X),例如:0xF(也就是十进制中的15)。
了解了进制的定义,我们再来看看各个进制之间的转换(通常都是十进制与其他进制之间的转换):
先说十进制转换为其他进制:十进制数÷相应进制=商······余数→商÷相应进制=新的商······余数,直到 商 为0为止;然后把余数从右到左依次排列,就是相应进制的数了
计算机是以二进制存储的,所以我们主要说一下转换为二进制的:
举个例子,把11转换为二进制,过程:
11÷2=5······1,5÷2=2······1,2÷2=1······0,1÷2=0······1,所以二进制就是0b1011;
再来一个八进制的吧,把21转换为八进制,过程:
21÷8=2······5,2÷8=0······2,所以八进制就是025,
把35转换为十六进制,过程:
35÷16=2······3,2÷16=0······2,所以十六进制就是0x23,
我们再说说其他进制转换为十进制:举个例子大家就明白了,
把0b1011转换为十进制,过程:
- 1×20 + 1×21 + 0×22 + 1×23 = 11
我们再来一个,把0x2AE转换为十进制:
- 14×160 + 10×161 + 2×162 = 486
说完了这个,我们再来说说有关原码、补码、反码的一些东西
二、有关原码、补码、反码的一些东西
我们这里统一都以byte类型共8位 来进行说明:
我们都知道计算机是以二进制存储的,而且是以补码的形式存储的,而且:
- 正整数:补码 = 原码;
- 负整数:补码= 反码 + 1;
- 原码就是一个正整数的二进制,
- 反码是原码的符号位(即最高位,正数为0,负数为1)不变,其他各位取反(0变1,1变0);
废话不多说,举个例子大家就明白了,我们来看看9的源码,补码:
因为9是正数,所以补码=源码,根据上面的进制转换我们知道9的二进制是0b1001,所以以byte类型的存储方式就是:00001001,
所以 9的补码=源码=00001001
那-9的补码、源码、反码呢?
-9的源码就是符号位取1,其他各位与9的源码相同,所以就是:-9的源码=10001001,-9的反码=11110110,-9的补码=11110111,所以-9在计算机中以byte类型的存储形式就是11110111(-9的补码)
我们知道了十进制转换为原码,再转换为补码,那反过来呢?怎么由补码求出原码呢?
其实很简单,就是把上面的步骤倒过来就可以了,需要注意的就是:
- 如果补码的符号位(即最高位)为0,则为正数,此补码=原码;
- 如果补码的符号位为1,则表示负数,这时需要减1,再去反码,最后得到负数的原码。
我们来举个例子,补码为00101011,求其原码,
因为符号位为0,表示正数,所以该补码就是原码;
再来一个,补码为10101011,求其原码,
因为符号位为1,表示负数,所以先减1,得到10101010,再取反码 为11010101,这就是其原码,为负数
三、位运算(&、|、^、~)
位运算 | 运算规则 |
---|---|
& (按位与) | 全1则1,否则为0 |
| (按位或) | 全0则0,否则为1 |
^ (按位异或) | 相同为0,不同为1 |
~ (按位取反) | 遇0则1,遇1则0 |
<<(按位左移) | 将符号左边的数的二进制位依次左移(符号右边为移动位数) |
>> (按位右移) | 将符号左边的数的二进制位依次右移(符号右边为移动位数) |
- 注意的一点是,按位异或的运算是可逆的,一个数按位异或另一个数两次,得到原数,例如6 ^ 9 ^ 9 = 6; 运用此特性,按位异或有一个很重要的作用就是:不使用临时中介变量,就可以直接交换两个值,
int num1 = 5, num2 = 6;
num1 = num1 ^ num2;
num2 = num2 ^ num1; //此时num2 = 5
num1 = num1 ^ num2; //此时num1 = 6
之所以会这样,我们来分析一下:num2 = num2 ^ ( num1 ^ num2 ) = num1 ^ ( num2 ^ num2 ) = num1 ^ 0 = num1
,此时num2 == num1 == 5 ;
然后num1 = num1 ^ num2 = ( num1 ^ num2 ) ^ num2 = ( num1 ^ num2 ) ^ num1 = num2
,此时num == num2 == 6;
而且我们要清楚( num1 ^ num2 ) ^ num2
这个式子中第一个num2是原来的num2(即值为6),第二个num2已经是原来的num1(即值为5)了
-
我们再来说一下0的按位取反(~0)为啥等于-1 :
- 以byte类型来说明,0的补码为00000000,则~0后得11111111,我们要注意此时的11111111是在计算机中存储的,所以是补码形式,因为符号位位1,所以该数为负数,通过上面讲过的补码转换为原码的步骤,可得原码为10000001,该原码也就是十进制中的-1了
-
那1的按位取反(~1)为啥等于-2呢?
- 其实跟上面的~0原理一样,我们同样以byte类型来说明,1的补码为00000001,按位取反后得到11111110,此时同样为补码的形式存储,减1、再取反后 可得原码为10000010,也就是十进制中的-2