秒懂!进制和位运算
关于进制
进制是计算机中数据的一种表示方法。 N 进制的数可以用 0~(N-1) 的数表示, 超过 9 的用字母 A-F 表示 。
十进制:用 0~9 的数表示 , 逢 10 进 1
二进制:由 0-1 组成
八进制:由 0-7 组成,逢 8 进 1
十六进制: 由 0-9,A-F 组成。0-9 对应 0-9,A-F 对应 10-15。字母不区分大小写
机制的转换
二进制转十进制
二进制数的第 0 位的权值是 2 的 0 次方,第一位是 2 的 1 次方......
所以,设有一个二进制数:101100100,转换为十进制为(从右向左):
八进制转十进制
八进制数的第 0 位的权值是 8 的 0 次方,第一位是 8 的 1 次方......
所以,设有一个八进制数:1507,转换为十进制为(从右向左):
十六进制转十进制
十六进制数的第 0 位的权值是 16 的 0 次方,第一位是 16 的 1 次方......
所以,设有一个十六进制数 2AF5,转换为十进制为(从右向左):
快速的进行 2 进制,10 进制,16 进制的相互转换
二进制的 8421
首先我们来看一个二进制数:1111,它是多少呢?你可能还要这样计算:1×2º+1×2¹+1×2²+1×2³=1×1+1×2+1×4+1×8=15。
我们必须直接记住 1111 每一位的权值,并且是从高位往低位记:8、4、2、1。
即,最高位的权值为 2³=8,然后依次是 2² =4,2¹=2,2º=1。
记住 8 4 2 1,对于任意一个 4 位的二进制数,我们都可以很快算出它对应的 10 进制值。
接下来我们练习 通过 8421 的方式 进行 快速的计算 , 2,10,16 进制的转换
二进制数转十六进制
以 4 位一段,分别转换为十六进制,如:
十六进制转二进制
反过来,当我们看到 FD 时,如何迅速将此十六进制转二进制呢?
看到 F,我们需知道它是 15,然后 15 如何用 8421 凑呢?
应该是:8 + 4 + 2 + 1,所以四位全为 1 :1111。
接着转换 D,看到 D,知道它是 13,13 如何用 8421 凑呢?
应该是:8 + 4 + 1,即:1101。
所以,FD 转换为二进制数,为:1111 1101
十进制转二进制
由于十六进制转换成二进制相当直接,所以,我们需要将一个十进制数转换成二进制数时,也可以先转换成十六进制,然后再转换成二进制。比如,十进制数 1234 转换成二制数,如果要一直除以 2,直接得到 2 进制数,需要计算较多次数。所以我们可以先除以 16,得到 16 进制数:
十六进制为:4D2
转二进制对应为:
即十进制 1234 转二进制为:0100 1101 0010
二进制转十进制
同样,如果一个二进制数很长,我们需要将它转换成十进制数时,除了前面学过的方法是,我们还可以先将这个二进制转换成十六进制,然后再转换为 10 进制。如一个 int 类型的二进制数如下:
我们按四位一组转换为十六进制:6 D E 5 A F 1 B
十六进制转化为十进制:
十进制转十六进制
采余数定理分解,例如将 487710 转成十六进制:
487710(10) = 7711E(16)
位运算
计算机中的计算都是以二进制来进行运算的,因此相比在代码中直接使用(+、-、*、/)运算符,合理使用位运算符能提高代码的执行效率。
与(&)
4 & 6 = 4
首先我们需要把两个十进制的数转换成二进制
用途
清零:若想将一个单元清零,只要与一个各位都为 0 的数值相与,结果就为零
判断奇偶:只要根据最末位判断是 0 还是 1 就可以判断,是 0 就是偶数,是 1 就是奇数
或(|)
4 & 6 = 6
首先我们需要把两个十进制的数转换成二进制
用途
常用来对一个数据的某些位设置为 1:若要将一个数 X=10101100 的低四位设置为 1,那么令 Y=00001111,X 与 Y 相或的结果就是将 X 的低四位设置为 1(X | Y = 10101111)
非(~)
在 Java 中,所有数据的表示方法都是以补码的形式表示,如果没有特殊说明,Java 中的数据类型默认是 int,int 数据类型是占 4 个字节,1 字节为 8 位,所以 int 为 32 位,32bit。
补码与原码关系:正数补码与原码相同,负数补码是原码减 1 后取反
注意:二进制中,最高位是符号位 1 表示负数,0 表示正数
了解了原码补码我们来看位非~运算符
例:~4
4 转为二进制是:0100
补码为:00000000 00000000 00000000 00000100
取反为:11111111 11111111 11111111 11111011(这就是~4 在计算机存储的补码)
需要将补码计算出原码然后转化为十进制,高位不变,取反+1
10000000 00000000 00000000 00000101
转为十进制为:-5
所以 ~4 = -5
异或(^)
4 ^ 6 = 6
首先我们需要把两个十进制的数转换成二进制
相同为 0,不同为 1
用途
交换两个数:一个数和另一个数异或两次得到还是原来的数
右移(>>)
4>>1 = 2
4 转为二进制是:0100
正数,高位补 0,负数,高位补 1
左移(<<)
4<<1 = 8
4 转为二进制是:0100
正数,高位补 0,负数,高位补 1
负数在非运算中已做说明,这里不在演示。
无符号右移(>>>)
无符号右移(>>>)只对 32 位和 64 位有意义。
在移动位的时候与右移运算符的移动方式一样的,区别只在于补位的时候不管是 0 还是 1,都补 0。
有趣的取模性质
取模 a % (2^n) 等价于 a & (2^n - 1),所以在 map 里的数组个数一定是 2 的乘方数,计算 key 值在哪个元素中的时候,就用位运算来快速定位。
版权声明: 本文为 InfoQ 作者【阿粤Ayue】的原创文章。
原文链接:【http://xie.infoq.cn/article/52990e15384a1f364929b1a77】。文章转载请联系作者。
评论