Android中的位运算

原创文章,如有转载,请注明出处:http://blog.csdn.net/yihui823/article/details/6754038


其实和java是一样的,java也通用。

我们人对数字的理解,是从十进制开始的。从小受到的教育,也是从 1+9 = 10开始的。但是,对于目前的计算机来说,它们的世界是二进制的世界。计算机用一个高电平表示1,用一个低电平表示0。

如果我们要表示十进制数10,对于计算机来说,必须转换成二进制数1010。当然,计算机不但用“0”和“1”来表示数据,还用“0”和“1”来表示字母,表示操作,表示运算,表示推理,表示一切的一切。对于计算机所有操作的原操作,都是“0”和“1”的操作。

对于这些计算机的原操作,也是和我们的认识不同的。我们学的基础运算,例如1+1=2,那是一个加法而已,是不能再切分的了。但是计算机的原操作,只有“与”、“或”、“异或”、“非”以及位移等操作。加法是需要用这些原操作组合起来才能实现的。

说的比较笼统。这个也不是一两句才能说清楚的。在现在的高级语言中,加法和位运算的操作符可以同时使用,所以我们也不需要太过深究位运算怎么实现加法,只要知道有位运算这么回事就行了。

以下是基础的位运算

0 & 0 = 0; 0& 1 = 0; 1 & 0 = 0; 1 & 1 = 1

0 | 0 = 0; 0 | 1= 1; 1 | 0 = 1; 1 | 1 = 1

0 ^ 0 = 0;1 ^ 0= 1;0 ^ 1 = 1; 1 ^ 1 = 0

另外,字节的概念需要说明一下。字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制。Java里的byte,就是字节。

对于无符号整数来说,一个字节能表示的最大的数,就是255了,也就是“11111111”。但是对于一个有符号的整数,因为需要把左边第一位用来表示正负,所以能表示的最大的数,就是127了。也就是“0111111”。能表示的最小的数也可以如此推算。

在java里面,一个int就是用4个字节来表示的。因为java没有无符号整数的类型,所以第一位一定是符号位。

如果我们把byte强制转换成int类型,int的最低的8位与byte相同,之前的3个字节,都用符号位来填补。也就是说,如果是一个负数byte,那么转化成int之后,前3个字节都是1。

我们可以用下面这段代码来看:

		byte b1 = 10;
		System.out.println("b1=" + Byte.toString(b1));
		System.out.println("b1转成int后的二进制:" + Integer.toBinaryString(b1));
		
		
		byte b2 = -10;
		System.out.println("b2=" + Byte.toString(b2));
		System.out.println("b2转成int后的二进制:" + Integer.toBinaryString(b2));

 

结果显示:

b1=10

b1转成int后的二进制:1010

b2=-10

b2转成int后的二进制:11111111111111111111111111110110

b1是正数,转成int型后,前面补0,所以还是00001010,只是0000在转String的时候去掉了。

b2是负数,转成int型后,前面补1,所以就是11111111111111111111111111110110了。

细心的朋友一定发现了不对劲的地方。是的,-10的二进制,最后几位是11110110,不是我们想象中的10001010。这里有个概念,叫补码。

为什么要有这么一个概念。还得从符号位来说。如果只是符号位来表示正负,后面的数据都一样,那么就会有个问题,+0和-0的事情。正数我们可以表示的从0~127,负数我们可以表示-0 ~ -127,那么一共只能表示255个数字,因为0和-0是一个数字。为了解决这个问题,所以有了补码的概念。也就是说,如果是负数,除了符号位用1表示外,剩下的位数都反一下,然后-1.

那么,-10的二进制的推算步骤,应该是:

1,10的二进制,去掉符号位是0001010

2,减一,就是0001001

3,反过来,就是1110110

4,加上符号位,就是11110110

这种情况下,就没有-0的概念了。10000000表示的数,应该是:

1, 去掉符号位,数据位是0000000

2, 因为符号位是1,所以需要补码计算

3, 反过来,就是1111111

4, 加1,就是10000000。

所以,10000000表示的十进制数是-128

这样,一个byte可以表示 -128 ~127,正好256个数字,一个都不浪费了。

如果我们只要显示byte的二进制数,那怎么办?那我们就先把byte转成int,然后把前面的3个byte都去掉,只留下最后一个byte的数据就行了。代码如下:

		byte b1 = 10;
		System.out.println("b1=" + Byte.toString(b1));
		System.out.println("b1的二进制:" + Integer.toBinaryString(0xff & b1));
		
		
		byte b2 = -10;
		System.out.println("b2=" + Byte.toString(b2));
		System.out.println("b2的二进制:" + Integer.toBinaryString(0xff & b2));

      

主要是因为我们找不到Byte类的toBinaryString函数,所以只好借Integer的用用啦。

这里还需要说明一下,位移操作。如果把一个byte左移一位,那么最右边将补一个0,最左边的数据就丢掉了。而右移则不同,最左边补的是符号位,也就是最高的那个位。如果是负数,右移后还是负数。

看这段代码:

		byte b1 = 10;
		System.out.println("位移前b1=" + Byte.toString(b1));
		System.out.println("位移前b1的二进制:" + Integer.toBinaryString(0xff & b1));
		b1 = (byte)(b1 >> 2);
		System.out.println("位移后b1=" + Byte.toString(b1));
		System.out.println("位移后b1的二进制:" + Integer.toBinaryString(0xff & b1));
		
		
		byte b2 = -10;
		System.out.println("位移前b2=" + Byte.toString(b2));
		System.out.println("位移前b2的二进制:" + Integer.toBinaryString(0xff & b2));
		b2 = (byte)(b2 >> 2);
		System.out.println("位移后b2=" + Byte.toString(b2));
		System.out.println("位移后b2的二进制:" + Integer.toBinaryString(0xff & b2));


结果就是:

位移前b1=10

位移前b1的二进制:1010

位移后b1=2

位移后b1的二进制:10

位移前b2=-10

位移前b2的二进制:11110110

位移后b2=-3

位移后b2的二进制:11111101

 

一般在什么情况下会用到位操作呢?我的一些总结:

1,  和设备打交道的时候

基本上和设备的接口,都是传递byte数组。byte数组如果需要转成字符串,自然不需要位运算,只需要根据码制进行解码即可。但是如果转成int/long等数值,则需要用位运算来转换。

2,  快速运算的时候

需要×2的时候,直接左移1位,操作很快,而且省CPU。

3,  节省内存的时候

直接用位运算去判断某个字节,比转成String判断更省事。

还有什么,我倒是一下子想不起来了。后面我会展示几段代码以表示位运算的好处。
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值