移位
来源:互联网 发布:nginx 403 权限 编辑:程序博客网 时间:2024/05/16 23:55
运算符巧用
看源码是每个程序员必过的坎儿,刚开始看源码真的太痛苦了….没办法,只有不断的看源码才能了解一些原理,才能快速的进步。在源码的过程中你坑定遇到过这样位运算那样位运算,当位运算你肯定清除,但是运算符一组合,就懵了。。。。什么鬼,反正我就是这样,就是知识我们不熟悉其中运算的效果而已。
计算机中是以补码的形式保存所有整数的
负数:源码除最高符号位,其余为按位取反得到反码,反码+1得到补码
正数:源码和补码相同
补码—>源码:补码-1=得到反码,发码出最高符号位,其余为取反得到原码
(>>):有移,(X>>Y)X为int类型,X转化为32位的二进制,如果为正数,左边空位用0补位,如果为负数,用1补位;相当于X除以2的y方
(>>>)(无符号有移):都用0 补位
- <<:移动后,右边有0补位;相当于X乘以2的Y方
关于移位运算符>>、<<、>>>并不是适合所有数值类型,只适合byte、short、char、int、long等整数类型进行运算;
总结:
1. 一个32位的int整数,右移(b>>a),当a>32时,系统用b%32得到结果才是移位的位数。例如:a>>33和a>>1结果是一样的(因为int类型只有32位),a>>32还是a本身。
2. 一个64位的long整数,右移(b>>a),当a>64时,系统用b%64得到结果才是移位的位数。例如:a>>64和a>>1结果是一样的,a>>64还是a本身。
2. 对于低于int类型的操作数(如byte、short、char)总是会自动转化为int在移位
^(异或)
相同为0,不同为1
1 1—>0
0 0—>0
1 0—>1
0 1—>1
特定位取反
最后一位取反:X^1(高位不变(位与0异或不变))
0111 ^ 0001--------------- 0110
对异或取反,叫做(同或)或者(异或非)
巧用技巧
奇偶数判断
0101 & 0001-------------- 0000
利用最有一位是否是1,判断是否是奇数;为1,就是奇数;为0就是偶数;
X&1=1,表示X为奇数
X&1=0,表示X为偶数
不用temp交换两个数
X=5,y=4
X^=y;y^=X;X^=y
即可交换X、y的值;
特定位取反
使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask),源源操作数异或操作即可
右数第k位取反:x ^ (1 < < (k-1))
取模运算转化为位运算
X%(2^n)<====>X&((2^n)-1)
清除特定位
源操作数X与掩码mask(特定位为0 其他位都为1)&
举例说明:这里我们要将5(0101)的第三位清除,mask=1011
0101& 1011-------------- 0001
总结一下公式:X&((1<
取特定位
同样是源操作数和mask(只不过这里特定位为1,其他位为0)与;就不在举例说明,可以参看后面的取出指定位部分
将int型变量a的右起的第k位置1
a=a|(1 <<(k-1))
把右数第k位变成0
x & ~ (1 < < (k-1))
求两个整数的平均值
(X+Y)+((X+Y)>>1)
判断一个整数是不是2的幂(是不是2的n次方(n=0,1…..))
(x&(x-1)==0)&&(X!=0)
——(Android运用)—-
使用位运算来表示共同具有哪些属性,对应为为1就表示具有该属性,为0就表示不具有该属性;
举个例子:
0x01(0001)表示可读
0x02(0010)可写
0x03(0011)表示可读可写
a&~b: 清除标志位b;a|b: 添加标志位b;a&b: 取出标志位b;a^b: 取出a与b的不同部分;
Android中对flag主要由三种操作
- 通过“|”运算向flag变量中增加某个Flag;
原因: 如果flag变量没有XXX_FLAG,则 | 完后flag对应的位为1,如果有XXX_FLAG,则 | 完后值不会变对应位还是1.
flag|=XX_Flag;
通过“&”判断flag变量中是否包含XX_Flag
flag & XXX_FLAG != 0 或者 flag & XXX_FLAG = XXX_FLAG
原因: 如果flag变量里包含XXX_FLAG,则&完后flag变量对应的位为1,因为XXX_FLAG的定义保证了只有一位非0,其他位都为0,所以如果是包含的话&运算后值不为0,值为此XXX_FLAG的值,不包含的话值为0.
flag&XX_Flag:得到的就是XX_Flag标志位的值即取出XX_Flag标志位;举例说明:
0011(可读可写) 0001 & 0010(可写) & 0010--------------- --------------- 0010(可写) 0010
可以看见取出对应的标志位状态,之前是改为是什么状态(是否是可写状态),与对应位掩码&后,就可以得到该标志位的状态。
Android中应用:
// 返回是否可点击 return (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
3. 取消属性( 取消flag变量中XX_flag)
flag&=~XX_flag;
原因:先对XXX_FLAG进行取反 则XXX_FLAG原来非0的那一位变为0,则使用&运算符后flag变量非0的那一位变为0,则意味着flag变量不包含XXX_FLAG
4. 标志位取反(比如之前是可读不可写状态0001,和掩码0011一异或,对应位(读、写标志位)的标志位都置反了,变成了0010(可写不可读了))
0001 ^ 0011 ----------------- 0010
Android中运用:
…… private static final int PRESSED = 0x00004000; int mPrivateFlags ; …… public void setPressed(boolean pressed) { if (pressed) { mPrivateFlags |= PRESSED; // 添加PRESSED状态 } else { mPrivateFlags &= ~PRESSED; // 取消PRESSED状态 } refreshDrawableState(); dispatchSetPressed(pressed); }
- 获取X指定低N位的集合
举例说明:获取233的第6位
11,101001 & 00,111111-------------------------- 00,101001可以推导出公式就是:X&(N<<k)-1
获取X高N位:
x & (((1 << n) - 1) << (sizeof(x)-n))
sizeof(X):表示X的位数,比如这里是8位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 移位
- 右移位,右移位
- 逻辑移位 算术移位
- 移位操作
- 移位操作
- listbox移位
- git error Large files detected解决办法
- Python web 框架 Flask 入门 macOS 下实践记录
- kafka学习(1)
- html定时刷新
- 今天
- 移位
- pagehelper
- mysql navicat 事件开启
- flex布局实现左右都不定宽的自适应布局
- [Android]关于Handler和Looper/AsyncTask异步任务
- iOS开发-面向切面编程之 Aspects 源码解析
- Expected one result (or null) to be returned by selectOne(), but found: 2
- 通过例子学习Lua
- 2009年系统架构师考试题详解