设为首页 收藏本站
查看: 514|回复: 0

[经验分享] PHP的二进制位移操作

[复制链接]

尚未签到

发表于 2015-8-27 13:58:42 | 显示全部楼层 |阅读模式
  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
  • /**  
  • * 无符号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));   
  • }
  • ?>

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-105112-1-1.html 上篇帖子: php 数组排序以及按照某个字段排序 下篇帖子: 提高PHP的运行效率的方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表