/**
* 位运算 加法实现 核心:逢二进一
* @param int $a 被加数
* @param int $b 加数
* @return int 和
*/
function add(int $a, int $b): int
{
// 0001 0011
$and = $a & $b; // 0001 按位与 两个都为1
$xor = $a ^ $b; // 0010 按位异或 一个为0,一个为1
if (!$and) {
return $a | $b; // 按位或 任何一个为1
}
if (!$xor) {
return $and << 1; // 左移
}
return add($and << 1, $xor);
}
/**
* 位运算 减法实现 核心:加法逆运算
* @param int $a 被减数
* @param int $b 减数
* @return int 差
*/
function subtract(int $a, int $b): int
{
return add($a, -$b); // 加法逆运算
}
/**
* 位运算 乘法实现 核心:2*3 => 2*[0011 3的二进制数] =>从右向左计算 2*[2^0]+2*[2^1] => 2+4 => 6
* @param int $a 被乘数
* @param int $b 乘数
* @return int 积
*/
function multiply(int $a, int $b): int
{
$sum = 0; // 乘积
$j = 0; // 移位
$b2 = decbin($b); // 二进制数
$len = strlen($b2); // 二进制数长度
for ($i = $len - 1; $i > -1; --$i, ++$j) {
if ($b2[$i])
$sum = add($sum, $a << $j); // 二进制加法
}
return $sum;
}
/**
* divide 位运算 除法实现 核心:减法运算,直到减到快要小于零,减法次数即为商,剩余数字即为余数
* @param int $a 被除数
* @param int $b 除数
* @return int 商
*/
function divide(int $a, int $b): int
{
$num = 0; // 商
$c = $a; // 余数
while ($c >= $b) {
$c = subtract($c, $b); // 二进制减法
++$num;
}
return $num;
}