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+javascript模拟Matrix画面
Oct 09 PHP
PHP 数组遍历方法大全(foreach,list,each)
Jun 30 PHP
php文档更新介绍
Jul 22 PHP
关于使用key/value数据库redis和TTSERVER的心得体会
Jun 28 PHP
php分页函数完整实例代码
Sep 22 PHP
php提示Warning:mysql_fetch_array() expects的解决方法
Dec 16 PHP
Thinkphp框架开发移动端接口(2)
Aug 18 PHP
php微信公众平台交互与接口详解
Nov 28 PHP
Thinkphp5.0自动生成模块及目录的方法详解
Apr 17 PHP
php多文件打包下载的实例代码
Jul 12 PHP
实现laravel 插入操作日志到数据库的方法
Oct 11 PHP
TP5框架实现签到功能的方法分析
Apr 05 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
php 向访客和爬虫显示不同的内容
2009/11/09 PHP
调整PHP的性能
2013/10/30 PHP
windows7下安装php的imagick和imagemagick扩展教程
2014/07/04 PHP
ThinkPHP通过AJAX返回JSON的两种实现方法
2014/12/18 PHP
Yii2.0 模态弹出框+ajax提交表单
2016/05/22 PHP
PHP生成唯一ID之SnowFlake算法
2016/12/17 PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
2017/11/17 PHP
利用PHP判断是手机移动端还是PC端访问的函数示例
2017/12/14 PHP
jquery 漂亮的删除确认和提交无刷新删除示例
2013/11/13 Javascript
移动节点的jquery代码
2014/01/13 Javascript
解决window.opener=null;window.close(),只支持IE6不支持IE7,IE8的问题
2014/01/14 Javascript
jQuery.lazyload+masonry改良图片瀑布流代码
2014/06/20 Javascript
node.js中的events.emitter.listeners方法使用说明
2014/12/10 Javascript
jQuery视差滚动效果网页实现方法经验总结
2016/09/29 Javascript
bootstrap multiselect 多选功能实现方法
2017/06/05 Javascript
浅谈箭头函数写法在ReactJs中的使用
2017/08/22 Javascript
基于jQuery的左滑出现删除按钮的示例
2017/08/29 jQuery
vue配置接口域名方法总结
2019/05/12 Javascript
python实现的一个火车票转让信息采集器
2014/07/09 Python
Python实现七彩蟒蛇绘制实例代码
2018/01/16 Python
Python3之读取连接过的网络并定位的方法
2018/04/22 Python
利用Python检测URL状态
2019/07/31 Python
python实现登录密码重置简易操作代码
2019/08/14 Python
softmax及python实现过程解析
2019/09/30 Python
CSS3 实现弹跳的小球动画
2020/10/26 HTML / CSS
瑞贝卡·明可弗包包官网:Rebecca Minkoff
2016/07/21 全球购物
澳大利亚运动鞋商店:Platypus Shoes
2019/09/27 全球购物
Hurley官方网站:扎根于海滩生活方式的全球青年文化品牌
2020/05/18 全球购物
构建高效课堂实施方案
2014/03/13 职场文书
开工典礼策划方案
2014/05/23 职场文书
人事行政经理岗位职责
2014/06/18 职场文书
校庆标语集锦
2014/06/25 职场文书
给妈妈洗脚活动方案
2014/08/16 职场文书
党在我心中演讲稿
2014/09/02 职场文书
2014年幼儿园重阳节活动方案
2014/09/16 职场文书
2015年语言文字工作总结
2015/07/23 职场文书