(转载请注明出处:http://blog.csdn.net/prince58)
我们先从两道J2ME的笔试题入手吧:
1、求下列代码执行以后expr的值
int expr = -4321 >>>30;
2、用位操作替换以下运算
a) a = b * 256 ;
b) a = b % 16 ;
c) a = b / 13 ;
这是两道Gameloft(智乐软件)的JAVA笔试题,主要是测试一下大家对位移操作的理解。如果你很熟悉位运算的话,第一题只用3秒钟就能等到答案,>>>是JAVA特有的右移运算符,无符号,左边补0。
因为受到硬件条件的限制,在手机上开发时都比较关注两个问题:时间和空间。手机上的运算速自然无法和PC上相比,所以很多开发者在写代码时都会使用位运算对代码做一些优化,这就是为什么大家常常看到别人的代码里有">>","<<"或“&”之类的位移操作。下面从两方面来说一下如果在开发中使用位操作来提高速度和节省存储空间。
使用位移速度快:
在手持设备上乘法和除法都是复杂的操作(有可能还要调用子函数来实现),速度上比位操作要慢(位操作只需一个指令周期即可完成),所以我们可以通过位移进行替换。乘以2的n次幂可以左位移n,除于2的n次幂可以右位移n。比如,x/256 = x>>8 (2的8次幂等于256) ,x*256 = x<<8 。还有上面所例的 a = b % 16 可以使用&来解决: a= b%(2^4) => a=b&(2^n-1) => a = b & 15;
使用位移来节省空间:
如ARGB的int型的颜色,用16进制表示为0xAARRGGBB ,就可以只用一个INT(32位)型存储,读取和修改其中的值时,可以通过位移进行处理。
int a = (pal[i] & 0xFF000000) >> 24;
int r = (pal[i] & 0x00FF0000) >> 16;
int g = (pal[i] & 0x0000FF00) >> 8;
int b = (pal[i] & 0x000000FF);
// pal[i]表示调色版的ARBG值。
有些游戏中要存储一些标识信息,而存储的标识信息往往只有一两个位,就可以考虑用位移来节省空间。举个例子:游戏中的地图是用tile(规定大小的小图块)拼成的,有些tile可以进行 X/Y翻转,地图信息byte mapData[]表示地图中每个tile的索引,那么我们如何来存每个tile的翻转信息呢?新建一个和mapData相同大小的byte数组,这显然有些浪费空间。地图的tile只有三种翻转方式:X翻转、Y翻转和XY同时翻转,表示成二进制就是01,10,11 ,无翻转用00表示,只需要两位就可以表示tile翻转的信息,而一个byte有8位,完全可以存储4个tile的翻转信息。假设用byte mapFlip[]表存翻转信息,侧他所占的空间是mapData的1/4,一下子将地图的翻转标识所占用的空间节省了3/4。mapData 数据从0开始每相连四个tile的翻转标识符存为mapFlip中的一个byte。读取也很方便:
flip = mapFlip[mapIndex >> 2] & 0XFF;
(flip >> ((3 - (mapIndex & 0X3)) << 1)) & 0X3;
// mapIndex表示在mapData的序号,mapIndex >> 2,表示其对应mapFlip的序号。
假设一个flip =114 (二进制为 01 11 00 10),mapIndex = 5,这个mapIndex对应的tile的翻转信息应该是 flip的 “11”两位。
有些地图编辑器有一种做法是将tile翻转的标识信息和tile的索引信息放在一个int[]或short[]中,翻转信息放在int或short的高位(如int的第31、30位)。
当然位操作的用处还有很多,以后想起了或是用到的时候再给大家总结一下吧。