svn地址:svn://gitee.com/zxadmin/live_z

2019年2月14日11:38:46

  1. <?php
  2.  
  3. /*
  4. * 位运算学习笔记
  5. *
  6. * 1,php所有的数都是有符号的,无法指定是否是无符号的 unsign
  7. * 2.计算机底层运算都是补码运算的
  8. * 3,0反码,补码都是0
  9. * 4,正数的反码,补码全都一样
  10. * 5,二进制的最高位是符号位,0是正数,1是负数
  11. * 6,负数的反码符号位不变,其他未取反
  12. * 7,负数的补码等于反码+1
  13. * 8,负数(取反)=》反码 +1 =》补码
  14. * 9,补码-1=》反码(取反)=》负数
  15. * 10,右移 低位溢出,符号位不变 ,并用符号位补溢出的到位
  16. * 11,符号位不变 低位补0
  17. *
  18. * 32位的1表示是 31个0+1
  19. * 64位的1表示是 63个0+1
  20. * 参考 http://php.net/manual/zh/function.decbin.php
  21. * 测试: print_r(decbin(-50)) 32 位
  22. *
  23. $a & $b And(按位与) 将把 $a 和 $b 中都为 1 的位设为 1。
  24. $a | $b Or(按位或) 将把 $a 和 $b 中任何一个为 1 的位设为 1。
  25. $a ^ $b Xor(按位异或) 将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。
  26. ~ $a Not(按位取反) 将 $a 中为 0 的位设为 1,反之亦然。
  27. $a << $b Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
  28. $a >> $b Shift right(右移) 将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
  29.  
  30. ⋅⋅右移 >>:将二进制进行右移,低位丢掉,高位补零 符号位不变 。
  31. ⋅⋅左移 <<:将二进制进行左移,低位补零,高位丢掉 符号位不变 。
  32. ----------------------------------------------------------------------------------------------------------------------
  33. &
  34. 按位与
  35. 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
  36. |
  37. 按位或
  38. 两个相应的二进制位中只要有一个为1,该位的结果值为1
  39. ^
  40. 按位异或
  41. 若参加运算的两个二进制位值相同则为0,否则为1
  42. ~
  43. 取反
  44. ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0
  45. <<
  46. 左移
  47. 用来将一个数的各二进制位全部左移N位,右补0
  48. >>
  49. 右移
  50. 将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数, 高位补0
  51.  
  52. 要使用八进制表达,数字前必须加上 0(零)。要使用十六进制表达,数字前必须加上 0x。要使用二进制表达,数字前必须加上 0b。
  53. Example #1 整数文字表达
  54. $a = 1234; // 十进制数
  55. $a = -123; // 负数
  56. $a = 0123; // 八进制数 (等于十进制 83)
  57. $a = 0x1A; // 十六进制数 (等于十进制 26)
  58. $a = 0b11111111; // 二进制数字 (等于十进制 255)
  59. *
  60. * printf() - 输出格式化字符串, using %b, %032b or %064b as the format
  61. */
  62.  
  63. final class BitOperation {
  64. /*
  65. * 注意:位运算只能支持int类型
  66. */
  67.  
  68. public static $format = true;
  69.  
  70. //计算原码 吧数字十进制转换成二进制,并补充字符到系统的位数指定长度的原码
  71. public static function OriginalCode(int $number) {
  72. $OriginalCode = self::DecimalToBinary($number);
  73. return $OriginalCode;
  74. }
  75.  
  76. //计算反码
  77. public static function InverseCode(int $number) {
  78. $OriginalCode = self::DecimalToBinary($number);
  79. // p($OriginalCode);
  80. $InverseCode = '';
  81. if ($number >= 0) {
  82. return $OriginalCode;
  83. } else {
  84. $array = str_split($OriginalCode);
  85. foreach ($array as $k => &$v) {
  86. //符号位不变
  87. if ($k == 0) {
  88. continue;
  89. }
  90. //1变0 0变1
  91. if ($v == '0') {
  92. $v = 1;
  93. } elseif ($v == '1') {
  94. $v = 0;
  95. }
  96. }
  97. foreach ($array as $k1 => $v1) {
  98. $InverseCode .= $v1;
  99. }
  100. }
  101. return $InverseCode;
  102. }
  103.  
  104. //计算补码
  105. public static function ComplementCode(int $number) {
  106. $InverseCode = self::InverseCode($number);
  107. $ComplementCode = '';
  108. if ($number >= 0) {
  109. return $InverseCode;
  110. } else {
  111. // $array = str_split($InverseCode);
  112. // for ($index = (count($array) - 1); $index >= 0; $index--) {
  113. // $str .= $return[$index];
  114. // }
  115. /*
  116. * 不好直接计算
  117. */
  118. return decbin($number);
  119. }
  120. return self::Format($ComplementCode);
  121. }
  122.  
  123. /*
  124. * 十进制转二进制
  125. * 或者直接借用 decbin函数直接转换效率更高,这次是学习代码,为了写清楚原理
  126. * 注意这里的效率慢其实只要 self::PhpDigit()函数造成的,如果定义死计算是64,32效率快很多倍
  127. */
  128.  
  129. public static function DecimalToBinary(int $number) {
  130. $return = [];
  131. $abs = abs($number);
  132. while ($abs > 0) {
  133. $return[] = $abs % 2;
  134. $abs = $abs >> 1;
  135. }
  136. $str = '';
  137. for ($index = (count($return) - 1); $index >= 0; $index--) {
  138. $str .= $return[$index];
  139. }
  140. $plus_or_minus = $number >= 0 ? true : false;
  141. return self::FillingLength($str, $plus_or_minus);
  142. }
  143.  
  144. //优化版 十进制转二进制
  145. public static function DecimalToBinaryFast(int $number) {
  146. $return = [];
  147. $str = decbin(abs($number));
  148. $plus_or_minus = $number >= 0 ? true : false;
  149. return self::FillingLength($str, $plus_or_minus);
  150. }
  151.  
  152. /*
  153. * $plus_or_minus true + false -
  154. */
  155.  
  156. public static function FillingLength($string = null, $plus_or_minus = true) {
  157. $length = self::PhpDigit();
  158. $res = '';
  159. if ($plus_or_minus) {
  160. $res = str_pad($string, $length, '0', STR_PAD_LEFT);
  161. } else {
  162. $res = str_pad($string, $length - 1, '0', STR_PAD_LEFT);
  163. $res = '1' . $res;
  164. }
  165. return $res;
  166. }
  167.  
  168. public static function Format($string = null, $separation = 4) {
  169. if (mb_strlen($string) == 32 || mb_strlen($string) == 64) {
  170. $re = chunk_split($string, $separation, ".");
  171. $re = trim($re, '.');
  172. $re = str_replace('.', '&nbsp;', $re);
  173. return $re;
  174. } else {
  175. return $string;
  176. }
  177. }
  178.  
  179. /*
  180. * 你的系统是64,但是你运行的php版本不一定是64特别是在windows上
  181. */
  182.  
  183. public static function PhpDigit() {
  184. $phpinfo = self::PhpInfoArray();
  185. if (strtolower($phpinfo['General']['Architecture']) == 'x86') {
  186. return 32;
  187. } else {
  188. return 64;
  189. }
  190. }
  191.  
  192. public static function PhpInfoArray() {
  193. ob_start();
  194. phpinfo();
  195. $info_arr = array();
  196. $info_lines = explode("\n", strip_tags(ob_get_clean(), "<tr><td><h2>"));
  197. $cat = "General";
  198. foreach ($info_lines as $line) {
  199. // new cat?
  200. preg_match("~<h2>(.*)</h2>~", $line, $title) ? $cat = $title[1] : null;
  201. if (preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val)) {
  202. $info_arr[trim($cat)][trim($val[1])] = trim($val[2]);
  203. } elseif (preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val)) {
  204. $info_arr[trim($cat)][trim($val[1])] = array("local" => trim($val[2]), "master" => trim($val[3]));
  205. }
  206. }
  207. return $info_arr;
  208. }
  209.  
  210. public static function CountIntOne_1(int $n) {
  211. //计算一个十进制数转换为二进制数中‘1’的个数
  212. //例如十进制11 = 二进制1011,则结果是3个1
  213. //解题思路:利用 n & (n - 1) 可以将最后一个1变0
  214. //xxxx1000 & (xxxx1000 - 1) = xxxx1000 & xxxx0111 = xxxx0000
  215. // 1011 & (1011 - 1) = 1011 & 1010 = 1010
  216. //直到最后一个1被与为0,得出结果
  217. $r = 0;
  218. while ($n != 0) {
  219. $r++;
  220. $n &= ($n - 1);
  221. }
  222. return $r;
  223. }
  224.  
  225. /*
  226. *
  227. */
  228.  
  229. public static function CountIntOne_2(int $n) {
  230. /*
  231. * 十进制转二进制过程计算余数
  232. * 1%2 = 1 1 2~0
  233. * 2%2 = 0 10 2~1
  234. * 3%2 = 1 11 2~0 + 2~1
  235. * 4%2 = 0 100 2~3
  236. * 5%2 = 1 101 2~0 + 2~3 5%2 = 1 1%2 =1
  237. *
  238. * 利用的是数学计算过程,因为是对2求余,所有有可能是0 1 两个元素,0就是二进制位数0 1就是二进制位数的1
  239. */
  240. $r = 0;
  241. while ($n > 0) {
  242. $t = $n % 2;
  243. $n = $n >> 1;
  244. if ($t == 1) {
  245. $r++;
  246. }
  247. }
  248. return $r;
  249. }
  250.  
  251. /**
  252. * @param int $a
  253. * @param int $b
  254. * @return int $a + $b;
  255. */
  256. public static function add(int $a, int $b): int {
  257. $sum = $a;
  258. while ($b) {
  259. $sum = $a ^ $b; // 不考虑进位
  260. $b = ($a & $b) << 1; // 只考虑进位
  261. $a = $sum;
  262. }
  263. return $sum;
  264. }
  265.  
  266. /**
  267. * 相反数 <= 二进制表达取反+1(补码)
  268. * @param int $n
  269. * @return int
  270. */
  271. public static function negateNumber(int $n): int {
  272. return self::add(~$n, 1);
  273. }
  274.  
  275. /**
  276. * a-b = a + (-b)
  277. * @param int $a
  278. * @param int $b
  279. * @return int
  280. */
  281. public static function minus(int $a, int $b): int {
  282. return self::add($a, self::negateNumber($b));
  283. }
  284.  
  285. /**
  286. * @param int $a
  287. * @param int $b
  288. * @return int $a * $b
  289. */
  290. public static function multiple(int $a, int $b): int {
  291. $res = 0;
  292. while ($b) {
  293. if (($b & 1)) {
  294. $res = self::add($res, $a);
  295. }
  296. $a <<= 1;
  297. $b >>= 1;
  298. }
  299. return $res;
  300. }
  301.  
  302. // public static function isNegative(int $n): bool {
  303. // return $n < 0;
  304. // }
  305. //-1就是负数, 0就是正数 直接右移31位即可看最左边第一个
  306. public static function isNegative(int $n) {
  307. return $n >> 31;
  308. }
  309.  
  310. public static function maxInt(int $n) {
  311. return PHP_INT_MAX;
  312. }
  313.  
  314. //交换两个int数
  315. public static function swap(int &$x, int &$y) {
  316. $x ^= $y;
  317. $y ^= $x;
  318. $x ^= $y;
  319. }
  320.  
  321. //交换两个int数,注意返回int
  322. public static function average(int $x, int $y) {
  323. return ($x & $y) + (($x ^ $y) >> 1);
  324. }
  325.  
  326. //判断奇偶
  327. public static function isOddEven(int $n) {
  328. return $n & 1;
  329. }
  330.  
  331. public static function abs($x) {
  332. $y = $x >> 31;
  333. return ($x ^ $y) - $y;
  334. }
  335.  
  336. /**
  337. * a/b a = MIN_INTEGER, b!=MIN_INTEGER ?
  338. * @param int $a
  339. * @param int $b
  340. * @return int
  341. */
  342. public static function p(int $a, int $b): int {
  343.  
  344. $x = self::isNegative($a) ? self::negateNumber($a) : $a;
  345. $y = self::isNegative($b) ? self::negateNumber($b) : $b;
  346. $res = 0;
  347. for ($i = 31; $i > -1; $i = self::minus($i, 1)) {
  348. if (($x >> $i) >= $y) {
  349. $res |= (1 << $i);
  350. $x = self::minus($x, $y << $i);
  351. }
  352. }
  353. return self::isNegative($a) ^ self::isNegative($b) ? self::negateNumber($res) : $res;
  354. }
  355.  
  356. /**
  357. * @return int $a / $b
  358. */
  359. public static function pide(int $a, int $b): int {
  360.  
  361. if ($b === 0) {
  362. throw new RuntimeException("pisor is 0");
  363. }
  364. if ($a === self::MIN_INTEGER && $b === self::MIN_INTEGER) {
  365. return 1;
  366. } else if ($b === self::MIN_INTEGER) {
  367. return 0;
  368. } else if ($a === self::MIN_INTEGER) {
  369. $res = self::p(self::add($a, 1), $b);
  370. return self::add($res, self::p(self::minus($a, self::multiple($res, $b)), $b));
  371. } else {
  372. return self::p($a, $b);
  373. }
  374. }
  375.  
  376. }

其实位运算的基础能力对于算法是很重要的,特别是在优化算法的时候,如果代码有问题进群反馈

参考:

https://www.cnblogs.com/kingkoo/p/6117690.html

https://www.cnblogs.com/XuYiHe/p/4966309.html

https://www.cnblogs.com/luowei010101/archive/2011/11/24/2261575.html

https://www.cnblogs.com/qiaogaojian/p/5873105.html

https://www.cnblogs.com/kiven-code/archive/2012/09/15/2686922.html

https://blog.csdn.net/lmhacm/article/details/77287571

PHP算法学习(5) 位运算的更多相关文章

  1. Java学习之位运算和逻辑运算符

    今天看了一下HashMap类的源码,在HashMap的源码中定义了初始空间的大小 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 当 ...

  2. php学习笔记位运算

    位运算 源码:用二进制表示一个数,这个码就是源码. 比如2====00000000 00000000 0000000 00000010 正数的反码 源码 补码都一样 负数的源码是符号位取反.第一个位  ...

  3. 曹工说JDK源码(3)--ConcurrentHashMap,Hash算法优化、位运算揭秘

    hashcode,有点讲究 什么是好的hashcode,一般来说,一个hashcode,一般用int来表示,32位. 下面两个hashcode,大家觉得怎么样? 0111 1111 1111 1111 ...

  4. 关于C/C++中的位运算技巧

    本篇文章讲述在学习CSAPP位运算LAB时的一些心得. 移位运算的小技巧 C/C++对于移位运算具有不同的策略,对于无符号数,左右移位为逻辑移位,也就是直接移位:对于有符号数,采用算术移位的方式,即左 ...

  5. N皇后-位运算优化

    N皇后问题 时间限制: 5 Sec  内存限制: 128 MB 题目描述 魔法世界历史上曾经出现过一个伟大的罗马共和时期,出于权力平衡的目的,当时的政治理论家波利比奥斯指出:“事涉每个人的权利,绝不应 ...

  6. 位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  7. 【Java基础】14、位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  8. 面试必备:高频算法题终章「图文解析 + 范例代码」之 矩阵 二进制 + 位运算 + LRU 合集

    Attention 秋招接近尾声,我总结了 牛客.WanAndroid 上,有关笔试面经的帖子中出现的算法题,结合往年考题写了这一系列文章,所有文章均与 LeetCode 进行核对.测试.欢迎食用 本 ...

  9. 剑指offer—算法之位运算(二进制中1的个数)

    位运算: 左移:m<<n将m左移n位,左移后低位补充0: 右移:m>>n将m右移n位,右移后高位补充的是符号位,负数补充1,整数补充0.(正数的边界值为(1,ox7FFFFFF ...

随机推荐

  1. Stm32型号查阅手册

  2. Synchronized 和 Volatile

    Synchronized : 称为重量级锁,经过优化后,也没那么重了 一.CAS 1.CAS:Compare and Swap, 翻译成比较并交换. 2.java.util.concurrent包中借 ...

  3. [好文mark] 深度学习中的注意力机制

    https://cloud.tencent.com/developer/article/1143127

  4. php exit die的区别

    exit 输出一个消息并且退出当前脚本 void exit([string $status]) void exit(int $status)中止脚本的执行.尽管调用了exit(),Shutdow函数以 ...

  5. Python 概念小屋

     Python 中的 if __name__ == '__main__' 该如何理解 python多进程的理解 multiprocessing Process join run      

  6. 【原创】大数据基础之Ambari(3)通过Ambari部署Airflow

    ambari2.7.3(hdp3.1) 安装 airflow1.10 ambari的hdp中原生不支持airflow安装,下面介绍如何通过mpack方式使ambari支持airflow安装: 1 下载 ...

  7. Python- redis缓存 可达到瞬间并发量10W+

    redis是什么? mysql是一个软件,帮助开发者对一台机器的硬盘进行操作. redis是一个软件,帮助开发者对一台机器的内存进行操作. redis缓存 可达到瞬间并发量10W+ 高并发架构系列:R ...

  8. GRPC单向/双向流

    开始食用grpc(之二)https://www.cnblogs.com/funnyzpc/p/9570992.html 开始食用grpc(之一)https://www.cnblogs.com/funn ...

  9. Vue中父子组件通讯——组件todolist

    一.todolist功能开发 <div id="root"> <div> <input type="text" v-model=& ...

  10. Cordova IOT Lesson003

    bot index.html <!DOCTYPE html> <html> <head> <title>Arduino蓝牙机械昆虫控制器</tit ...