PHP字符串运算结果,PHP 实现后缀表达式(接受四则运算字符串,输出计算结果,附代码)...

最近接触了一个有趣的需求:给定变量a、b、c、d等若干,要求由用户输入的普通四则运算字符串(包含加减乘除括号),算出具体的值。

例如,a=1,b=2,c=3,d=4,给出 a+b/(d-c),应计算出结果为3,若为 a*b/(c-1) 则应计算出结果为1

这种情况下,第一反应可能是用数字值将字符串里的变量替换,然后通过eval()执行。或者是将字符串中的每一项通过正则一个一个扣出来再进行计算。

但这样的逻辑太粗暴,代码也太丑陋,其实大可不必如此。 此时,让我们将目光移向美丽的数据结构与算法。

首先,我们了解一下 后缀表达式。

表达式一般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,

这称为中缀表达式(Infix Expression),如A+B。我们日常生活中使用的就是此种方式

波兰数学家Jan Lukasiewicz提出了另一种数学表示法,它有两种表示形式:

把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;

把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+

我们今天要探讨的就是后缀表达式

我们如何使用它呢?

首先我们要将平时用的中缀表达式转为后缀表达式。

在此之前,我们需要一种常见的数据结构:栈,在这一步,我们需要两个栈,操作数栈、运算符栈

1、从左至右扫描一中缀表达式。

2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数栈

3、若读取的是运算符

(1) 该运算符为左括号”(“,则直接存入运算符栈。

(2) 该运算符为右括号”)”,则输出运算符栈中的运算符到操作数栈,直到遇到左括号为止。

(3) 该运算符为非括号运算符:

(a) 若比运算符栈栈顶的运算符优先级高或相等,则直接存入运算符栈。

(b) 若比运算符栈栈顶的运算符优先级低,则输出栈顶运算符到操作数栈,并将当前运算符压入运算符栈。

4、当表达式读取完成后运算符栈中尚有运算符时,则依序取出运算符到操作数栈,直到运算符栈为空。

此时,将操作数栈转为一个字符串,它就是由我们输入的中缀表达式转化而来的后缀表达式

那么后缀表达式如何进行计算呢?

1、从左到右扫描后缀表达式。

2、如果扫描的项目是操作数,则将其压入操作数栈,并扫描下一个项目。

3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。

4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。

5、将运算结果重新压入栈。

6、重复步骤2-5,直到后缀表达式扫描完毕,栈中即为结果值。

Talk is cheap,let me show you the code

接下来是使用PHP编写的这样一个工具类。可以接受传入一个表达式和表达式各项对应值 的数组,给出计算之后的结果。

使用方式:

RPNotation::calculate($exp, $exp_values);

例如:

$exp = "a+b-(c*d)/e";

$exp_values = ["a" => 1, "b" => 2, "c" => 3, "d" => 2, "e" => 3];

RPNotation::calculate($exp, $exp_values);

结果会是1

代码内容 :

1, '-' => 1, '*' => 2, '/' => 2, "(" => 0, ")" => 0];

/*

params:

$exp-普通表达式,例如 a+b*(c+d)

$exp_values-表达式对应数据内容,例如 ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]

*/

public static function calculate($exp, $exp_values) {

$exp_arr = self::parse_exp($exp);//将表达式字符串解析为列表

if (!is_array($exp_arr)) {

return NULL;

}

$output_queue = self::nifix2rpn($exp_arr);

return self::calculate_value($output_queue, $exp_values);

}

//将字符串中每个操作项和预算符都解析出来

protected static function parse_exp($exp) {

$match = [];

preg_match_all(self::PATTERN_EXP, $exp, $match);

if ($match) {

return $match[0];

}else {

return NULL;

}

}

//将中缀表达式转为后缀表达式

protected static function nifix2rpn($input_queue){

$exp_stack = [];

$output_queue = [];

foreach($input_queue as $input) {

if (in_array($input, array_keys(self::EXP_PRIORITIES))){

if ($input == "(") {

array_push($exp_stack, $input);

continue;

}

if ($input == ")") {

$tmp_exp = array_pop($exp_stack);

while ($tmp_exp && $tmp_exp != "(") {

array_push($output_queue, $tmp_exp);

$tmp_exp = array_pop($exp_stack);

}

continue;

}

foreach(array_reverse($exp_stack) as $exp) {

if (self::EXP_PRIORITIES[$input] <= self::EXP_PRIORITIES[$exp]) {

array_pop($exp_stack);

array_push($output_queue, $exp);

}else {

break;

}

}

array_push($exp_stack ,$input);

}else {

array_push($output_queue, $input);

}

}

foreach(array_reverse($exp_stack) as $exp) {

array_push($output_queue, $exp);

}

return $output_queue;

}

//传入后缀表达式队列、各项对应值的数组,计算出结果

protected static function calculate_value($output_queue, $exp_values) {

$res_stack = [];

foreach($output_queue as $out) {

if (in_array($out, array_keys(self::EXP_PRIORITIES))) {

$a = array_pop($res_stack);

$b = array_pop($res_stack);

switch ($out) {

case '+':

$res = $b + $a;

break;

case '-':

$res = $b - $a;

break;

case '*':

$res = $b * $a;

break;

case '/':

$res = $b / $a;

break;

}

array_push($res_stack, $res);

}else {

if (is_numeric($out)) {

array_push($res_stack, intval($out));

}else {

array_push($res_stack, $exp_values[$out]);

}

}

}

return count($res_stack) == 1 ? $res_stack[0] : NULL;

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业实战_23_MyCat SQL防火墙

接上一篇&#xff1a;企业实战_22_MyCatSQL拦截 https://blog.csdn.net/weixin_40816738/article/details/100073474 文章目录1. SQL防火墙_白名单配置2. 白名单测试3. SQL防火墙_黑名单配置4. SQL防火墙_黑名单测试SQL防火墙&#xff1a;包括2个标签<whitehost></whi…

同样是消息队列,Kafka凭什么速度那么快?

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 邴越来源 | 技术琐话Kafka的消息是保存或缓存在磁盘上的&#xff0c;一般认为在磁盘上读写数据是会降低性能的&#xff0c;因为寻址会比较消耗时间&#xff0c;但是实际上&#xff0c;Kafka的特性之一就是高吞吐率。即使是普…

企业实战_10_Mycat集成ZK实现配置同步

主机名IP地址角色数据库mycat192.168.43.32MYCAT ,MYSQL,ZKmycat&#xff08;全局自增id&#xff09;node1192.168.43.104ZKMYSQLorder_db01和order_db01node2192.168.43.217ZK,MYSQLorder_db03和order_db04node3192.168.43.172MYCAT ,MYSQLmycat&#xff08;全局自增id&#x…

亚马逊重组游戏开发部门:数个未发布游戏被“扼杀”;台积电明年开始为苹果iPhone生产5nm处理器……...

关注并标星星CSDN云计算极客头条&#xff1a;速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01;每周三次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go 盒马送餐机器人、无人化再进…

psp中java,PSP编程概述

元旦准备买NDS&#xff0c;顺带关注了下PSP&#xff0c;其实是想&#xff0c;或许买PSP也不错~PSP很像一个平台&#xff0c;提供了很多东西&#xff0c;譬如官方的PS模拟器~在上面编程也是个不错的想法。国外的一个网站提供了很多信息&#xff0c;PS2Dev Network (http://www.p…

企业实战_18_MyCat_ZK集群安装部署

接上一篇&#xff1a;企业实战_17_MyCat水平扩展_跨分片查询_ER分片 https://gblfy.blog.csdn.net/article/details/100066013 文章目录一、使用ZK记录Mycat的配置1. 操作步骤2. 服务器部署分布二、zk集群安装部署2.1. 安装jdk并验证2.2. ZK下载2.3. node1下载同步zk2.4. 基础配…

分布式精华问答 | 分布式与集群的区别是什么?

什么是分布式计算&#xff1f;所谓分布式计算是一门计算机科学&#xff0c;它研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分&#xff0c;然后把这些部分分配给许多计算机进行处理&#xff0c;最后把这些计算结果综合起来得到最终的结果。1Q&#xff1a;…

php模板解析引擎 单独,ThinkPHP模板引擎实现和常见问题

模板引擎由来早期做PHP开发WEB应用都是把PHP代码和HTML模板混在一起&#xff0c;模板引擎的诞生主要就是为了解决后端与前端的完全分离(现在来看其实是属于不完全分离)的问题&#xff0c;让开发与美工可以分工合作(虽然实际上最终模板工作大多仍然是由后端开发人员完成)&#x…

Mycat设置开机自启

接上一篇&#xff1a;实战_21_Mycat_MySql更新数据库失败 --read-only https://blog.csdn.net/weixin_40816738/article/details/100059688 下载mycat wget http://dl.mycat.io/1.6.5/Mycat-server-1.6.5-release-20180122220033-linux.tar.gz解压即安装mycat tar -zxf Mycat…

最近,京东AR又爆出哪般神奇?

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 刘晶晶只用一部手机就可在线“试用”口红&#xff0c;效果堪比美妆男主李佳琪&#xff0c;厉不厉害&#xff1f;只要轻轻一点就可一目了然购买的家具在家中摆放的效果怎样&#xff0c;神不神奇&#xff1f;时间飞快&#xff…

zookeeper开机自启动

编辑rc.local vim /etc/rc.d/rc.local2.需要指定jdk路径以及zookeeper启动路径 export JAVA_HOME/app/jdk1.8.0_144 /app/zookeeper-3.4.11/bin/zkServer.sh start3. 启动zookeeper cd /app/zookeeper-3.4.11/bin ./zkServer.sh start查看zk启动状态 /app/zookeeper-3.4.11…

绘制曲线 matlab,matlab绘制曲线图文

二维图形 三维图形 特殊二、三维图形 图形处理 实例 - 1 1.曲线图 Matlab作图是通过描点、连线来实现的,故在 画一个曲线图形之前,必须先取得该图形上的一系 ......例1 在0≤x≤2区间内,绘制曲线 y2e- MATLAB绘图 二维数据曲线图...第5讲 MATLAB绘图 电气工程系 李颖琼 6.1.1绘…

10分钟读懂什么是容器云?

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 宝哥devops运维来源 | http://t.cn/ECwSNgj容器技术是近几年云行业发展中不可缺少的一环。Docker和k8s的大热极大可能会推动云计算PAAS层的完善和普及。那么容器云到底是怎样的技术形态&#xff1f;究竟是概念还是可落地的应…

企业实战_19_MyCat初始化ZK并配置Mycat支持ZK

接上一篇&#xff1a;企业实战_18_MyCat_ZK集群安装部署 https://gblfy.blog.csdn.net/article/details/100075631 文章目录一、初始化集群中的数据1. 配置复制2. 初始化zookeeper集群中的数据二、验证数据是否被初始化到集群中2.1. 进入mycat01服务节点2.2. 使用ls命令查看当前…

Hadoop精华问答 | 基于Hadoop的数据中心有什么好处?

戳蓝字“CSDN云计算”关注我们哦&#xff01;2006年项目成立的一开始,“Hadoop”这个单词只代表了两个组件——HDFS和MapReduce。到现在的13个年头,这个单词代表的是“核心”&#xff0c;今天我们就来看看关于Hadoop的精华问答。1Q&#xff1a;基于Hadoop的数据中心有什么好处&…

企业实战_20_MyCat使用HAPpoxy对Mycat负载均衡

上一篇&#xff1a;企业实战_19_MyCat初始化ZK并配置Mycat支持ZK https://gblfy.blog.csdn.net/article/details/100087824 解决了引入多个mycat节点之间配置文件信息同步问题 如何在多个mycat之间进行负载均衡的问题&#xff1f; 在某一个mycat节点出现宕机之后&#xff0c;我…

安全,从写第一行代码开始!

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 刘晶晶伴随5G时代的脚步渐进&#xff0c;物联网发展也将成井喷式增长&#xff0c;“网络安全”这个老生常谈的话题似乎进入了新阶段。数据是天使&#xff1f;还是魔鬼&#xff1f;归根结底&#xff0c;没有安全保障的物联网终…

python模块里的函数及说明,Python模块 time与datetime模块的函数说明及使用实例

time模块模块time包含用于获取当前时间,操作时间和日期.从字符串中读取日期,将日期格式化为字符串的函数.日期可表示为实数,也可表示为包含9个整数的元组例如tuple(2018,12,24,12,2,56,-1,-1,-1)------------------------------------------------------索引 字段 值0-----年--…

Linux zookeeper下载、单点部署

说明地址ziphttp://mirror.bit.edu.cn/apache/zookeeper/stable/apache-zookeeper-3.5.5-bin.tar.gz命令下载wget http://mirror.bit.edu.cn/apache/zookeeper/stable/apache-zookeeper-3.5.5-bin.tar.gz http://archive.apache.org/dist/zookeeper/zookeeper-3.5.7/apache-zoo…

聚科技精英,享开源之美- 2019 Open Source Summit 主题演讲+项目亮点

2019年6月24-26日&#xff0c;在上海世博中心&#xff0c;由Linux基金会主办的LinuxCon ContainerCon CloudOpen大会&#xff08;简称LC3&#xff09;将与CNCF主办的KubeCon CloudNativeCon大会合体&#xff0c;自此&#xff0c;大会正式更名为KubeCon CloudNativeCon Ope…