进制详解(程序员必须会的基本功)
进制介绍
-
对于整数,有四种表示方式:
-
**二进制:**0,1 ,满 2 进 1.以 0b 或 0B 开头。
-
**十进制:**0-9 ,满 10 进 1。(我们现实生活中最常见的就是十进制)
-
**八进制:**0-7 ,满 8 进 1. 以数字 0 开头表示。
-
**十六进制:**0-9 及 A(10)-F(15),满 16 进 1. 以 0x 或 0X 开头表示。此处的 A-F 不区分大小写。
-
-
下图为进制的图示:
进制的转换
-
思考:既然我们有四种不同的进制,那么我们不同进制之间是怎么转换的呢?
-
进制的转换总共分为以下四组进制的转换:
-
第一组:
- 二进制转十进制
- 八进制转十进制
- 十六进制转十进制
第二组:
-
十进制转二进制
-
十进制转八进制
-
十进制转十六进制
第三组
-
二进制转八进制
-
二进制转十六进制
第四组
- 八进制转二进制
- 十六进制转二进制
第一组:
二进制转十进制
-
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以2的(位数-1)次方,然后求和。
-
案例:请将0b1011转换成十进制的数:
- 首先我们将 0b1011 按照上面的规则一次提取出来计算,然后求和;
- 如下图:
-
如上图所示,二进制 0b1011 转成十进制就是数字11。
八进制转十进制
- 规则:从最低位(右边)开始,将每个位上的数提取出来,乘以8的(位数-1)次方,然后求和。
- 案例:请将0256转换成十进制的数:
- 首先我们将0256按照上面的规则一次提取出来计算,然后求和;
- 0256 = 6 * 8的(1-1)次方 + 5 * 8的(2-1)次方 + 2 * 8的(3-1)次方 = 6 + 40 + 128 = 174
- 根据计算所得,十进制0256转成十进制就是数字174。
十六进制转十进制
- 规则:从最低位(右边)开始,将每个位上的数提取出来,乘以16的(位数-1)次方,然后求和。
- 案例:请将0x26A转换成十进制的数:
- 首先我们将0x26A按照上面的规则一次提取出来计算,然后求和;
- 0x26A = 10 * 16的(1-1)次方 + 6 * 16的(2-1)次方 + 2 * 16的(3-1)次方 = 10 + 96 + 512 = 618
- 根据计算所得,十六进制 0x26A 转成十进制就是数字618;
第二组:
十进制转二进制
-
规则:将该数不断除以 2,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。
-
案例:请将 36 转成二进制
-
具体算法如下图:
-
按照上图我们得到的二进制是100100,但是我们写二进制的时候一般四位一写,所以我们补齐就是00100100,所以十进制的36转成二进制就是 0b00100100;
十进制转八进制
-
规则:将该数不断除以 8,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的八进制。
-
案例:请将234转成八进制
-
具体算法如下图:
- 按照上图我们得到的八进制是352,所以十进制的234转成八进制就是0352;
十进制转十六进制
-
规则:将该数不断除以 16,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的十六进制。
-
案例:请将 456 转成十六进制
-
具体算法如下图:
- 按照上图我们得到的十六进制是1 12 8,根据十六进制中10-15用英文字母A-F表示,那么12为C,1 12 8为1C8,所以十进制的456转成十六进制就是 0x1C8;
第三组:
二进制转八进制
-
规则:从低位开始,将二进制数每三位一组,转成对应的八进制数即可。
-
案例:请将 ob10100010 转成八进制
ob10100010
=> 0b10(0 * 2^0 + 1 * 2^1)100(0 * 2^0 + 0 * 2^1 + 1 * 2^2)010(0 * 2^0 + 1 * 2^1 + 0 * 2^2)
=> 0b10(2)100(4)010(2)
=> 242
-
所以二进制 0b10100010 转成八进制就是 0242;
二进制转十六进制
-
规则:从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。
-
案例:请将 ob11010101 转成十六进制
ob11010101 => ob1101(D)0101(5) => 0xD5
-
所以二进制 0b11010101 转成十六进制就是 0xD5;
第四组:
八进制转二进制(跟二进制转八进制相反)
-
规则:将八进制数每 1 位,转成对应的一个 3 位的二进制数即可。
-
案例:请将 0237 转成二进制
02(010)3(011)7(111) = 0b10011111
-
所以八进制 0237 转成二进制就是 0b10011111;
十六进制转二进制(跟二进制转十六进制相反)
-
规则:将十六进制数每 1 位,转成对应的 4 位的一个二进制数即可。
-
案例:请将 0x23B 转成二进制
0x2(0010)3(0011)B(1011) = 0b001000111011
-
所以十六进制 0x23B 转成二进制就是 0b001000111011;
二进制
二进制在运算中的说明
- 二进制是逢二进位的进位制,0、1是基本算符。
- 现代的电子计算机技术全部采用的二进制,因为他们只是用0、1两个数字符号,非常简单方便,易于用电子方式实现。
- 计算机内部处理的信息,都是采用二进制数来表示的。二进制(Binary)数用0和1两个数字及其组合来表示任何数。进位规则是"逢2进1",数字1在不同的位上代表不同的值,按从右至左的次序,这个值以二倍递增。
原码、反码、补码(重点 难点)
精简为几句话:(对于有符号的而言)
- 二进制的最高位是符号位:最左边为0表示正数,最左边为1表示负数;
- 正数的原码、反码、补码都一样;
- 负数的反码 = 他的原码的符号位不变,其他位取反;
- 负数的补码 = 他的反码+1 , 负数的反码 = 负数的补码 -1 ;
- 0 的反码补码都是 0 ;
- Java中的数都是有符号的;
- 在计算机运算的时候,都是以补码的方式运算的
- 当我们看运算结果的时候,都要看他的原码
位运算符
- java 中有 7 个位运算(&、|、 ^ 、~、>>、<<和 >>>)
- 按位与 & : 两位全为1,结果为1,否则为0 ;
- 按位或 | : 两位有一个为1,结果为1,否则为0 ;
- 按位异或 ^ : 两位有一个0,一个为1,结果为1,否则为0 ;
- 按位取反 ~ :0变成1,1变成0 ;
- 算术右移 >>:低位溢出,符号位不变,并用符号位补溢出的高位;
- 算术左移 <<: 符号位不变,低位补 0 ;
- 逻辑右移>>>: 也叫无符号右移,运算规则是: 低位溢出,高位补 0
- 特别说明:没有 <<< 符号
小练习
-
请看下面的代码段,回答 a,b,c,d,e 结果是多少?(已在代码中回答)
public static void maiin(String []args){ // 1 向右位移 2 位 //本质就是1/2/2,因为是int类型,所以输出0 int a=1>>2; //本质就是-1/2/2,因为是int类型,所以输出-1 int b=-1>>2;//算术右移 //本质就是1*2*2,所以输出4 int c=1<<2;//算术左移 //本质就是-1*2*2,所以输出-4 int d=-1<<2;// //本质就是3/2/2,因为是int类型,所以输出0 int e=3>>>2;//无符号右移 //a,b,c,d,e 结果是多少 System.out.println("a="+a);//0 System.out.println("b="+b);//-1 System.out.println("c="+c);//4 System.out.println("d="+d);//-4 System.out.println("e="+e);//0 }
-
请回答在 java 中,下面的表达式运算的结果是:
- ~2 = ?
~2 = ? // ~ 按位取反 /* *因为是int类型,所以有4个字节,所以先把2转换为原码 *00000000 00000000 00000000 00000010 *计算机运算的时候,都是以补码的方式运算的 *正数的原码、反码、补码都一样;正好2为正数 *所以~2的补码与2完全相反,所以~2的补码为: *11111111 11111111 11111111 11111101 *取反过后首位为1,所以变成了负数 *负数的补码 = 他的反码+1 , 负数的反码 = 负数的补码 -1 ; *所以~2的反码 = ~2的补码-1,为 *11111111 11111111 11111111 11111100 *当我们看运算结果的时候,都要看他的原码 *因为负数的反码 = 他的原码的符号位不变,其他位取反; *所以~2的原码为10000000 00000000 00000000 00000011 *转为十进制结果为 -3 *所以计算所得 ~2 = -3 */
- 2 & 3 = ?
2 & 3 = ? // 2 按位与 3 /*根据上面一样的算法:上面两个都为正数,所以原码、反码、补码都一样; *2的补码00000000 00000000 00000000 00000010 *3的补码00000000 00000000 00000000 00000011 *计算2 按位与 3 ,计算过后的补码为 *00000000 00000000 00000000 00000010 *因为是正数,所以原码与补码一样,转为十进制结果为 2 *所以计算所得 2 & 3 = 2 ; */
- 2 | 3 = ?
2 | 3 = ? //2 按位或 3 /*与上面那题一样 *2的补码00000000 00000000 00000000 00000010 *3的补码00000000 00000000 00000000 00000011 *计算2 按位或 3 ,计算过后的补码为 *00000000 00000000 00000000 00000011 *因为是正数,所以原码与补码一样,转为十进制结果为 3 *所以计算所得 2 | 3 = 3 ; */
- -3 ^ 3 = ?
-3 ^ 3 = ? //^ -3 按位异或 3 /*一样的步骤 *-3的原码 10000000 00000000 00000000 00000011 *-3的反码 11111111 11111111 11111111 11111100 *-3的补码 11111111 11111111 11111111 11111101 * 3的补码 00000000 00000000 00000000 00000011 *按位异或 ^ : 两位有一个0,一个为1,结果为1,否则为0 *所以 -3 按位异或 3 的结果为: *计算所得补码 11111111 11111111 11111111 11111110 *转换对应反码 11111111 11111111 11111111 11111101 *转换对应原码 10000000 00000000 00000000 00000010 *转为十进制结果为 -2; *所以计算所得 -3 ^ 3 = -2 ; */