时间:2021-07-01 10:21:17 帮助过:45人阅读
例子 名称 结果
$a & $b And(按位与) 将把 $a 和 $b 中都为 1 的位设为 1。
$a | $b Or(按位或) 将把 $a 或者 $b 中为 1 的位设为 1。
$a ^ $b Xor(按位异或) 将把 $a 和 $b 中不同的位设为 1。
~ $a Not(按位非) 将 $a 中为 0 的位设为 1,反之亦然。
$a << $b Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $b Shift right(右移) 将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
但是 我想知道 应该怎么算 就是提前 可以知道这个运算的结果
比如说
12 & 13
134 | 234
98 ^ 7
等等 这些
关于php的位运算 手册中 是这样介绍的
例子 名称 结果
$a & $b And(按位与) 将把 $a 和 $b 中都为 1 的位设为 1。
$a | $b Or(按位或) 将把 $a 或者 $b 中为 1 的位设为 1。
$a ^ $b Xor(按位异或) 将把 $a 和 $b 中不同的位设为 1。
~ $a Not(按位非) 将 $a 中为 0 的位设为 1,反之亦然。
$a << $b Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $b Shift right(右移) 将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
但是 我想知道 应该怎么算 就是提前 可以知道这个运算的结果
比如说
12 & 13
134 | 234
98 ^ 7
等等 这些
如果我没理解错的话 ... 你要问的是如何手动进行位运算对吧 ...
位运算是二进制的运算方式 ... 你想做十进制数字的位运算操作的话先要将它们转成二进制 ...
如何手动转化进制我就不赘述了 ... 你可以自己去看 ... 主要说位运算 ...
假如我们有两个数字 123 和 321 ... 转化成二进制之后是 001111011 和 101000001 ...
我们从字面意思上理解 ... 按位与
... 就是按照每一位做 与 这个操作 ... 如下 ...
001111011 & 101000001 ------------- 001000001 = 65
也就是说 123 & 321 = 65 ... 按位或
和 按位异或
皆同此理 ... 很简单我就不写了 ...
按位非
... 单纯的为当前数字取反 ... 比如我们手动计算 ~123 的过程如下 ...
~ 000 ... 001111011 --------------------- 111 ... 110000100 = 看上去很大的数字
我想这个问题你也注意到了 ... 把一个数字 按位非
之后 ... 前面会产生很多很多的 1 ...
会导致这个数字看上去非常大 ... 大到难以计算 ...
但事实上不是 ... 我们的操作系统无法存储无限大的整数 ...
事实上它只能存储从 0 开始到 2 的 n 次方的所有数字 ... n 可以很大但不是无限大 ...
但这产生了一个新的问题 ... 就是操作系统不认识负数 ... 而负数又很常见 ...
所以人们又约定 ... 当一个二进制数字长度是 n 且最高位是 1 的时候 ... 就表示这是一个负数 ...
也就是操作系统接受了负的 2 的 n - 1 次方到 2 的 n 次方 - 1 这个范围内的整数 ... 很完美 ...
回到问题上来 ... 那么看起来很大的这个数字其实是个负数 ... 负多少呢 ..?
算法是这样 ... 去掉最高位之后做按位非操作 ... 然后加上负号再减一 ...
也就是 ~123 = -(~(~123))-1 = -124 ... 原理很复杂但表现起来超简单 ...
接下来 左移
和 右移
... 一样是字面的意思 ... 比如 123 << 2 ...
001111011 << 2 --------------- 00111101100 = 492
左移的时候空出来的位补零 ... 右移的时候多出去的位直接丢弃 ...
也就是说所有数字如果不停左移或者右移的话 ... 最后结果一定是 0 ...
写到这儿突然感觉好像是在跟小朋友讲基础知识一样 ... 嘛 ... 总之就是这样啦 ...