PHP 使用位运算实现四则运算的代码

计算机最基本的操作单元是字节,一个字节由8个位组成,一个位只能存储一个0或1。所有数据在计算机中都是采用二进制,即 1 和 0 的编码存储和运算,这次尝试在 PHP 中使用位运算实现四则运算。

Posted in PHP onMarch 09, 2021
  • 原码:将最高位作为符号位(0表示正,1表示负),其它数字位代表数值本身的绝对值
  • 反码:正数反码和原码一样;如果是负数,符号位不变,其余各位取反
  • 补码:正数补码和原码一样;负数补码为反码加 1

计算机中的数使用 补码  的形式存储

加法

二进制中只有 0 和 1,0 + 0、0 + 1 都不需要进位,但 1 + 1 则需要进位。所以,首先通过 抑或 运算得到不需要进位的那些位相加的结果。然后进行 与 运算,当相加的两位都为 1 时结果为 1。所以如果与运算的结果大于 0 说明需要进位,此时将与运算的结果按位左移 1 位,此时将左移的结果与抑或运算得到的结果重新进行上述的运算过程,直到与运算的结果为 0。

function add($summand, $addend) {
	$sum = $summand ^ $addend;
	// 判断进位
	$carry = $summand & $addend;
	while ($carry <<= 1) {
		$summand = $sum;
		$addend = $carry;
		$sum = $summand ^ $addend;
		$carry = $summand & $addend;
	}
	return $sum;
}

 

减法

function subtract($minuend, $subtrahend) {
	// 先求得减数的补码,然后求和
	$subtrahend = add(~$subtrahend, 1);

	return add($minuend, $subtrahend);
}

 

乘法

乘法也可以看作是加法的变种,例如 m * n 可以看作是 n 个 m 相加的结果。但乘法使用位运算还有更快捷的实现方式。例如 3 * 10:3 的二进制表示为 0011,10 的二进制表示为 1010

0 0 1 1
×      1 0 1 0
————————————
0 0 0 0
0 0 1 1 0
0 0 0 0 0 0
0 0 1 1 0 0 0
————————————
0 0 1 1 1 1 0

乘法计算的结果为:当乘数的位的值为 1 时,将被乘数按位左移相应的位数,最后将这些按位左移后得到的结果相加及时最后的结果。

function multiply($multiplicand, $multiplicator) {
	// 判断符号位
	$flag = ($multiplicand ^ $multiplicator) < 0 ? false: true;
	// 被乘数和乘数取绝对值
	$multiplicand = $multiplicand < 0 ? add(~$multiplicand, 1) : $multiplicand;
	$multiplicator = $multiplicator < 0 ? add(~$multiplicator, 1) : $multiplicator;
	$product = 0;
	$multiplicator = decbin($multiplicator);
	$length = strlen($multiplicator);
	for ($i = 0; $i < $length; $i++) {
		if ($multiplicator[$i]) {
			$product += $multiplicand << $length - $i - 1;
		}
	}
	if (!$flag) {
		$product = add(~$product, 1);
	}
	return $product;
}

 

除法

同乘法类似,除法可以看作是被除数可以减去多少个除数。

function divide($dividend, $divisor) {
	// 判断符号位
	$flag = ($dividend ^ $divisor) < 0 ? false: true;
	// 取得被除数符号位
	$dividend_flag = $dividend < 0 ? false: true;
	// 取绝对值
	$dividend = $dividend < 0 ? add(~$dividend, 1) : $dividend;
	$divisor = $divisor < 0 ? add(~$divisor, 1) : $divisor;

	$quotient = 0;
	$remainder = 0;

	if ($dividend < $divisor) {
		// 被除数小于除数的情况
		$remainder = $dividend;
		return 'quotient = '.$quotient.' remainder = '.$remainder;
	}

	while ($dividend >= $divisor) {
		$i = 0;
		$mul_divisor = $divisor;

		while ($dividend >= ($mul_divisor << 1)) {
			$i++;
			$mul_divisor <<= 1;
		}

		$dividend -= $mul_divisor;
		$quotient += 1 << $i;
	}

	$remainder = $dividend;
	if (!$flag) {
		$quotient = add(~$quotient, 1);
	}
	if (!$dividend_flag) {
		$remainder = add(~$remainder, 1);
	}

	return 'quotient = '.$quotient.' remainder = '.$remainder;
}

需要指出的是,上面的代码在实现过程中并没有考虑数据的溢出。
两个很大的数相加可能会溢出;
正数减负数也可能溢出;
两个大数相乘也会溢出;
任何数除以 0 都会溢出。

PHP 相关文章推荐
PHP和XSS跨站攻击的防范
Apr 17 PHP
用php+javascript实现二级级联菜单的制作
May 06 PHP
关于session在PHP5的配置文件中的详细设置参数说明
Apr 20 PHP
PHP curl 获取响应的状态码的方法
Jan 13 PHP
PHP调用.NET的WebService 简单实例
Mar 27 PHP
php检查页面是否被百度收录
Oct 28 PHP
常用PHP封装分页工具类
Jan 14 PHP
浅谈PHP的exec()函数无返回值排查方法(必看)
Mar 31 PHP
thinkphp5框架实现的自定义扩展类操作示例
May 16 PHP
PHP设计模式之组合模式定义与应用示例
Feb 01 PHP
php post换行的方法
Feb 03 PHP
PHP中类与对象功能、用法实例解读
Mar 27 PHP
让你的PHP,APACHE,NGINX支持大文件上传
Mar 09 #PHP
PHP常用字符串输出方法分析(echo,print,printf及sprintf)
Mar 09 #PHP
PHP中echo与print区别点整理
Mar 09 #PHP
PHP filter_var() 函数, 验证判断EMAIL,URL等
Mar 09 #PHP
PHP读取文件或采集时解决中文乱码
Mar 09 #PHP
利用PHP内置SERVER开启web服务(本地开发使用)
Mar 09 #PHP
PHP7 windows支持
Mar 09 #PHP
You might like
ThinkPHP的cookie和session冲突造成Cookie不能使用的解决方法
2014/07/01 PHP
PHP开启opcache提升代码性能
2015/04/26 PHP
Linux环境下php实现给网站截图的方法
2016/05/03 PHP
php中输出json对象的值(实现方法)
2018/03/07 PHP
用php定义一个数组最简单的方法
2019/10/04 PHP
Jquery中显示隐藏的实现代码分析
2011/07/26 Javascript
JS高级拖动技术 setCapture,releaseCapture
2011/07/31 Javascript
30个经典的jQuery代码开发技巧
2014/12/15 Javascript
Jquery 全选反选实例代码
2015/11/19 Javascript
jQuery的Each比JS原生for循环性能慢很多的原因
2016/07/05 Javascript
Node.js连接postgreSQL并进行数据操作
2016/12/18 Javascript
jQuery实现一个简单的轮播图
2017/02/19 Javascript
vue 使用Jade模板写html,stylus写css的方法
2018/02/23 Javascript
浅谈express.js框架中间件(middleware)
2019/04/07 Javascript
vue实现多级菜单效果
2019/10/19 Javascript
JavaScript 监听组合按键思路及代码实现
2020/07/28 Javascript
浅谈实现在线预览PDF的几种解决办法
2020/08/10 Javascript
Python使用sorted排序的方法小结
2017/07/28 Python
Python用for循环实现九九乘法表
2018/05/31 Python
Python爬虫常用小技巧之设置代理IP
2018/09/13 Python
python+opencv实现霍夫变换检测直线
2020/10/23 Python
python使用Plotly绘图工具绘制水平条形图
2020/03/25 Python
哈工大自然语言处理工具箱之ltp在windows10下的安装使用教程
2020/05/07 Python
python开发前景如何
2020/06/11 Python
python 匿名函数与三元运算学习笔记
2020/10/23 Python
HTML5利用约束验证API来检查表单的输入数据的代码实例
2016/12/20 HTML / CSS
日本著名的平价时尚女性购物网站:Fifth
2016/08/24 全球购物
英国时尚女装购物网站:Missguided
2018/08/23 全球购物
预备党员党校学习自我评价分享
2013/11/12 职场文书
教师应聘自荐信范文
2014/03/14 职场文书
村安全生产责任书
2014/08/25 职场文书
个人四风对照检查材料
2014/09/26 职场文书
教师先进事迹材料
2014/12/16 职场文书
《比的意义》教学反思
2016/02/18 职场文书
Spring Boot 排除某个类加载注入IOC的操作
2021/08/02 Java/Android
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技