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 相关文章推荐
我的论坛源代码(三)
Oct 09 PHP
杏林同学录(六)
Oct 09 PHP
PHP JS Ip地址及域名格式检测代码
Sep 27 PHP
PHP获取当前相对于域名目录的方法
Jun 26 PHP
php验证码实现代码(3种)
Sep 07 PHP
PHP Oauth授权和本地加密实现方法
Aug 12 PHP
针对多用户实现头像上传功能PHP代码 适用于登陆页面制作
Aug 17 PHP
php封装的smarty类完整实例
Oct 19 PHP
php array_pop 删除数组最后一个元素实例
Nov 02 PHP
PHP编程 SSO详细介绍及简单实例
Jan 13 PHP
php redis实现对200w用户的即时推送
Mar 04 PHP
PHP编程实现csv文件导入mysql数据库的方法
Apr 29 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
咖啡的种类和口感
2021/03/03 新手入门
用libtemplate实现静态网页生成
2006/10/09 PHP
Zend Framework实现多文件上传功能实例
2016/03/21 PHP
PHP-FPM运行状态的实时查看及监控详解
2016/11/18 PHP
利用javascript/jquery对上传文件格式过滤的方法
2009/07/25 Javascript
JavaScript 解析Json字符串的性能比较分析代码
2009/12/16 Javascript
JQuery的html(data)方法与&amp;lt;script&amp;gt;脚本块的解决方法
2010/03/09 Javascript
比较新旧两个数组值得增加和删除的JS代码
2013/10/30 Javascript
js冒泡、捕获事件及阻止冒泡方法详细总结
2014/05/08 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
js使用DOM操作实现简单留言板的方法
2015/04/10 Javascript
Javascript函数式编程简单介绍
2015/10/11 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
jquery实现静态搜索功能(可输入搜索文字)
2017/03/28 jQuery
基于bootstrap页面渲染的问题解决方法
2018/08/09 Javascript
Nodejs中的JWT和Session的使用
2018/08/21 NodeJs
React手稿之 React-Saga的详解
2018/11/12 Javascript
解决JS表单验证只有第一个IF起作用的问题
2018/12/04 Javascript
微信小程序使用wx.request请求服务器json数据并渲染到页面操作示例
2019/03/30 Javascript
[53:13]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-GAMING
2014/05/22 DOTA
python模拟新浪微博登陆功能(新浪微博爬虫)
2013/12/24 Python
分享一下Python 开发者节省时间的10个方法
2015/10/02 Python
Python六大开源框架对比
2015/10/19 Python
python3实现全角和半角字符转换的方法示例
2017/09/21 Python
在Python中增加和插入元素的示例
2018/11/01 Python
python的pytest框架之命令行参数详解(上)
2019/06/27 Python
使用Matplotlib 绘制精美的数学图形例子
2019/12/13 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
HTML5 本地存储之如果没有数据库究竟会怎样
2013/04/25 HTML / CSS
十佳大学生事迹材料
2014/01/29 职场文书
父亲节活动策划方案
2014/08/24 职场文书
委托书如何写
2014/08/30 职场文书
大雁塔英文导游词
2015/02/10 职场文书
求职自荐信范文(优秀篇)
2015/03/27 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
《绝招》教学反思
2016/02/20 职场文书