php移位运算、移位操作学习笔记
发布:smiling 来源: PHP粉丝网 添加日期:2014-02-10 12:26:02 浏览: 评论:0
位运算应用口诀
清零取位要用与,某位置一可用或
若要取反和交换,轻轻松松用异或
移位运算
要点
1 它们都是双目运算符,两个运算分量都是整形,结果也是整形。
2 "<<" 左移:右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2。
3 ">>"右移:右边的位被挤掉。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。
4 ">>>"运算符,右边的位被挤掉,对于左边移出的空位一概补上0。
位运算符的应用 (源操作数s 掩码mask)
(1) 按位与-- &
1 清零特定位 (mask中特定位置0,其它位为1,s=s&mask)
2 取某数中指定位 (mask中特定位置1,其它位为0,s=s&mask)
(2) 按位或-- |
常用来将源操作数某些位置1,其它位不变。 (mask中特定位置1,其它位为0 s=s|mask)
(3) 位异或-- ^
1 使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask)
2 不引入第三变量,交换两个变量的值 (设 a=a1,b=b1)
目 标 操 作 操作后状态
a=a1^b1 a=a^b a=a1^b1,b=b1
b=a1^b1^b1 b=a^b a=a1^b1,b=a1
a=b1^a1^a1 a=a^b a=b1,b=a1
二进制补码运算公式:
-x = ~x + 1 = ~(x-1)
~x = -x-1
-(~x) = x+1
~(-x) = x-1
x+y = x - ~y - 1 = (x|y)+(x&y)
x-y = x + ~y + 1 = (x|~y)-(~x&y)
x^y = (x|y)-(x&y)
x|y = (x&~y)+y
x&y = (~x|y)-~x
x==y: ~(x-y|y-x)
x!=y: x-y|y-x
x< y: (x-y)^((x^y)&((x-y)^x))
x<=y: (x|~y)&((x^y)|~(y-x))
x< y: (~x&y)|((~x|y)&(x-y))//无符号x,y比较
x<=y: (~x|y)&((x^y)|~(y-x))//无符号x,y比较
应用举例
(1) 判断int型变量a是奇数还是偶数
a&1 = 0 偶数
a&1 = 1 奇数
(2) 取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1
(3) 将int型变量a的第k位清0,即a=a&~(1<<k)
(4) 将int型变量a的第k位置1, 即a=a|(1<<k)
(5) int型变量循环左移k次,即a=a<<k|a>>16-k (设sizeof(int)=16)
(6) int型变量a循环右移k次,即a=a>>k|a<<16-k (设sizeof(int)=16)
(7)整数的平均值
对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法:
- int average(int x, int y) //返回X,Y 的平均值
- {
- return (x&y)+((x^y)>>1);
- }
(8)判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂
- boolean power2(int x)
- {
- return ((x&(x-1))==0)&&(x!=0);
- }
(9)不用temp交换两个整数
- void swap(int x , int y)
- {
- x ^= y;
- y ^= x;
- x ^= y;
- }
(10)计算绝对值
- int abs( int x )
- {
- int y ;
- y = x >> 31 ;
- return (x^y)-y ; //or: (x+y)^y
- }
(11)取模运算转化成位运算 (在不产生溢出的情况下)
a % (2^n) 等价于 a & (2^n - 1)
a * (2^n) 等价于 a<< n
(13)除法运算转化成位运算 (在不产生溢出的情况下)
a / (2^n) 等价于 a>> n 例: 12/8 == 12>>3
(14) a % 2 等价于 a & 1
(15) if (x == a) x= b;
else x= a;等价于 x= a ^ b ^ x;
(16) x 的 相反数 表示为 (~x+1)
最后补充一些关于二进制位移操作
PHP主要是设计于文本操作的,其实PHP不适合做数学运算,效率也不高,不过因为这次的项目中有个东西必须使用到二进制位移操作,在PHP上面遇到了一些麻烦。
因为PHP只有32位有符号整数,没有64位长整型,也没有无符号整数。其整型的范围是-231-1~231,超出这个范围的,将被解释为浮点数。因此,0xFFFFFFFF,直接打印,显示的是4294967295,及232:
>> 0xFFFFFFFFF
4294967295
>> gettype(0xFFFFFFFF)
'double'
而在32位有符号整型中,0xFFFFFFFF应表示-1:
>> (int)0xFFFFFFFFF
-1
而PHP不支持浮点数的二进制位移操作,如果要进行,会先转换为整型,最后的结果,也将按照整型来返回:
- >> 1 << 31
- -2147483648
- >> 1 << 30
- 1073741824
- >> 1 << 32
- 1
- >> 0xFFFFFFFF >> 1
- -1
同时PHP的向右位移操作,高位会填充符号位,而且PHP没有提供类似Java的>>>来强制填充0:
- >> 1 << 32
- 1
- >> 0xFFFFFFFF >> 1
- -1
- >> 0xFFFFFFFF >> 2
- -1
- >> 0xFFFFFFFF >> 3
- -1
- >> 0xFFFFFFFF >> 31
- -1
如何解决这个问题呢,我考虑过使用BCMath数学函数库,直接处理字符串表示的整数,或者是GMP/BigInt扩展等。不过我想既然使用字符串,那么我可以字符串地彻底一些,把数字转换成32个二进制的字符串,再手工填充0,最后转换回来。
不知道哪位有更好的方法,请告诉我,另外,其实代码可以扩展为任意位2进制的位移操作,这里我没有做,PHP代码如下:
- <?php
- /**
- * 无符号32位右移
- * @param mixed $x 要进行操作的数字,如果是字符串,必须是十进制形式
- * @param string $bits 右移位数
- * @return mixed 结果,如果超出整型范围将返回浮点数
- */
- function shr32($x, $bits){
- // 位移量超出范围的两种情况
- if($bits <= 0){
- return $x;
- }
- if($bits >= 32){
- return 0;
- }
- //转换成代表二进制数字的字符串
- $bin = decbin($x);
- $l = strlen($bin);
- //字符串长度超出则截取底32位,长度不够,则填充高位为0到32位
- if($l > 32){
- $bin = substr($bin, $l - 32, 32);
- }elseif($l < 32){
- $bin = str_pad($bin, 32, '0', STR_PAD_LEFT);
- }
- //取出要移动的位数,并在左边填充0
- return bindec(str_pad(substr($bin, 0, 32 - $bits), 32, '0', STR_PAD_LEFT));
- }
- /**
- * 无符号32位左移
- * @param mixed $x 要进行操作的数字,如果是字符串,必须是十进制形式
- * @param string $bits 左移位数
- * @return mixed 结果,如果超出整型范围将返回浮点数
- */
- function shl32 ($x, $bits){
- // 位移量超出范围的两种情况
- if($bits <= 0){
- return $x;
- }
- if($bits >= 32){
- return 0;
- }
- //转换成代表二进制数字的字符串
- $bin = decbin($x);
- $l = strlen($bin);
- //字符串长度超出则截取底32位,长度不够,则填充高位为0到32位
- if($l > 32){
- $bin = substr($bin, $l - 32, 32);
- }elseif($l < 32){
- $bin = str_pad($bin, 32, '0', STR_PAD_LEFT);
- }
- //取出要移动的位数,并在右边填充0
- return bindec(str_pad(substr($bin, $bits), 32, '0', STR_PAD_RIGHT));
- }
- ?>
Tags: php 移位 运算 移位
- 上一篇:php5类型约束学习笔记
- 下一篇:php判断变量是否是整数的两种方法
相关文章
- ·PHP 是什么?(2013-11-12)
- ·Php.ini文件位置在哪里 Php.ini文件找不到(2013-11-12)
- ·PHP 数据类型(2013-11-12)
- ·php 获取当前脚本的url(2013-11-12)
- ·php技术生成静态页面的实现(2013-11-13)
- ·缺陷月项目启动 披露PHP脚本语言漏洞(2013-11-13)
- ·在PHP中全面阻止SQL注入式攻击(2013-11-13)
- ·php生成随机密码的几种方法(2013-11-13)
- ·PHP中使用FCKeditor2.3.2配置(2013-11-13)
- ·如何使用PHP开发高效的WEB系统(2013-11-13)
- ·php:树形结构的算法(2013-11-13)
- ·php4和php5区别(2013-11-13)
- ·php数据库连接(2013-11-13)
- ·如何正确理解PHP的错误信息(2013-11-13)
- ·php页面漏洞分析及相关问题解决(2013-11-13)
- ·当在连接PHP时,抱怨一些数值没有定义参考?(2013-11-27)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)