位运算加速技巧
本方法可以让C、C++语言指令进一步接近汇编指令的执行效率,提高嵌入式系统的速度和稳定性。
1.位运算原则:
- &(与逻辑):有0出0,全1出1;
- |(或逻辑):有1出1,全0出0;
- ~(非逻辑):空即是色,色即是空;
- ^(异或):相异出1,相同出0;
2. 如果乘上一个2的倍数数值,可以改用左移运算(Left Shift) 加速 300%
x = x * 2;
x = x * 64;
//改为:
x = x << 1; // 2 == 21
x = x << 6; // 64 == 26
3. 如果除上一个 2 的倍数数值,可以改用右移运算加速 350%
x = x / 2;
x = x / 64;
//改为:
x = x >> 1; // 2 == 21
x = x >> 6; // 64 == 26
4. 数值转整数加速 10%
x = int(1.232)
//改为:
x = 1.232 >> 0;
5. 交换两个数值(swap),使用 XOR 可以加速20%
var t:int = a;
a = b;
b = t;
//equals:
a = a^b;
b = a^b;
a = a^b;
6. 正负号转换,可以加入 300%
i = -i;
//改为
i = ~i + 1; // NOT 写法
//或
i = (i ^ -1) + 1; // XOR 写法
7. 取余数,如果除数为 2 的倍数,可利用 AND 运算加速 600%
x = 131 % 4;
//equals:
x = 131 & (4 - 1);
8. 利用 AND 运算检查整数是否为 2 的倍数,可以加速 600%
isEven = (i % 2) == 0;
//equals:
isEven = (i & 1) == 0;
9. 加速 Math.abs 600% 的写法1,写法2 又比写法1加速 20%
//写法1
i = x < 0 ? -x : x;
//写法2
i = (x ^ (x >> 31)) - (x >> 31);
//写法3
i=x^(~(x>>31)+1)+(x>>31);
10. 比较两数值相乘之后是否拥有相同的符号,加速 35%
eqSign = a * b > 0;
//equals:
eqSign = a ^ b > 0;
11.颜色位运算存储与分离
首先,颜色各个分量一般是以每8位为一个单位。
8位,8bit,即一个字节,10进制数的取值范围是0~255,一般用16进制表示,0x开头,取值范围是0x00到0xFF(不区分大小写)。
颜色一般有24位和32位两种表示方法。
- 24位颜色:每8位表示RGB中的一个分量。RGB颜色分量的值越大的时候最终颜色越偏向于这个颜色。
- 32位颜色:除了每8位表示RGB中的一个分量,还有一个8位用于表示透明度,表示为ARGB形式。
A即alpha值,alpha值为0时颜色为透明,alpha值为最大值时颜色为完全不透明,即可完全覆盖处于它下面的其他颜色,无其他颜色可以透过它而显示出来。
具体进行位移操作如下图:
表示颜色分量的数要想转化成一个整个的颜色,就必须和其他的分量组合,每个分量放在自己应当处于的位置,就应该进行位移操作。
tips:图中的颜色值34,23和88都是十六进制表示的,所以移位操作的时候可以直接移动位置表示。
移位后就是整体移动相应的位数,一个字母代表四位。
R移动16位,G移动8位,B不需要移动。
如果有A值,则A需要向左移动24位。
需要注意的是,不管是用什么进制表示,十进制还是十六进制还是二进制,位移操作都是二进制范畴的。
11.1 RGB 色彩分离
反向的转换则是右移。
知道一个颜色整体值,想提取某一个颜色分量,方法就是向右移动相应的位数,然后做一个与运算,与0xFF做与运算可以提取最低的两位。
var 24bitColor:uint = 0xff00cc;
var r:uint = 24bitColor >> 16;
var g:uint = 24bitColor >> 8 & 0xFF;
var b:uint = 24bitColor & 0xFF;
var 36bitColor:uint= 0xff342388;
var a:uint = color >>> 24 //注意这里是>>>,无符号右移位操作,右移24位,把342388移出,得到0xff
var r:uint = color >> 16 & 0xff;//右移16位,把2388移出,取0x34
var g:uint = color >> 8 & 0xff;//右移8位,把88移出,得0x3423,与0xff按位与操作,得0x23
var b:uint = color & 0xff;//得到0x88
11.2 RGB 色彩合并
var r:uint = 0xff;
var g:uint = 0x00;
var b:uint = 0xcc;
var 24bitColor:uint = r << 16 | g << 8 | b;
var a:uint = 0x01;
var r:uint = 0xff;
var g:uint = 0x00;
var b:uint = 0xcc;
var 36bitColor:uint= a<<24 | r << 16 | g << 8 | b;