PHP基于堆栈实现的高级计算器功能示例


Posted in PHP onSeptember 15, 2017

本文实例讲述了PHP基于堆栈实现的高级计算器功能。分享给大家供大家参考,具体如下:

当我们得到一个字符串运算式该如何去得出它的运算结果呢?

这时候我们就能使用堆栈的算法很巧妙的解决这个问题。

思路是这样的:(我们利用php函数substr循环去截取这个字符串运算式,依次取出这个字符串的值【我们得从第一个字符开始截取】,我们将开始截取位置设为一个循环增长的变量,初始化为【$index=0】),同时还需要创建两个栈,一个专门存放数字【$numStack】,一个存放运算符【$operStack】,我们还需要一个可以判断是否是运算符号的函数,将每次截取的值放入这个自定义函数中,返回一个可以区别为数字或运算符的标识,通过对这个标识的判断确定值是数字还是运算符,是数字就插入数栈,是运算符的话就插入符号栈。插入数栈的话可直接插入,但是符号栈的话需要特殊处理一下[【如果符号栈为空则直接插入,不为空:我们要将插入的符号与栈内的符号进行运算优先级比较(可以定义一个函数来判定符号优先级,把 *  和 / 假定为1  把 + 和 - 假定为0  假设数字大的优先级高,如此就能得出运算符优先级),当待插入的符号优先级小于等于栈内顶端的运算符优先级,就从数栈弹出两个值  符号栈弹出一个运算符 将它们进行运算】

下面是一个php的实例【参考自韩顺平老师的php算法教程】

<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8'/>
</head>
<h1>高级计算器</h1>
<?php
/**
 * 一个栈类
 */
class MyStack{
      public $top=-1;//默认是-1,表示该栈是空的
      public $maxSize=15;//$maxSize表示栈最大容量
      public $stack=array();//
      //入栈的操作
      public function push($val)
      {
        //先判断栈是否已经满了
        if($this->top==$this->maxSize-1){
          echo '<br/>栈满,不能添加';
          return;
        }
        $this->top++;
        $this->stack[$this->top]=$val;
      }
      //出栈的操作,就是把栈顶的值取出
      public function pop()
      {
        //判断是否栈空
        if($this->top==-1){
          echo '<br/>栈空1';
          return;
        }
        //把栈顶的值,取出
        $topVal=$this->stack[$this->top];
        $this->top--;
        return $topVal;
      }
      //显示栈的所有数据的方法.
      public function showStack()
      {
        if($this->top==-1){
          echo '<br/>栈空2';
          return;
        }
        echo '<br/>当前栈的情况是....';
        for($i=$this->top;$i>-1;$i--){
          echo '<br/> stack['.$i.']='.$this->stack[$i];
        }
      }
      //判断是否是一个运算符
      public function isOper($val)
      {
        if ($val=='+'||$val=='-'||$val=='*'||$val=='/')
        {
          return true;
        }
      }
      //判断栈是否为空
      public function isEmpty()
      {
        if ($this->top==-1) return true;
      }
      /**
       * 比较运算符的优先级
       * 我把 * 和/运算符的优先级看作1
       * +和- 看作0
       * 通过它们之间的比较就能得出它们的优先级谁更高
       */
      public function PRI($oper)
      {
        if ($oper=='*'||$oper=='/')
        {
          return 1;
        } else if ($oper=='+'||$oper=='-') {
          return 0;
        }
      }
      //返回栈顶端的值
      public function getTop()
      {
        return $this->stack[$this->top];
      }
      //计算
      public function getResult($num1,$num2,$oper)
      {
        switch ($oper)
        {
          case '+':
            $res = $num2+$num1;
          break;
          case '-':
            $res = $num2-$num1;
          break;
          case '*':
            $res = $num2*$num1;
          break;
          case '/':
            $res = $num2/$num1;
          break;
        }
        return $res;
      }
    }
    //需要进行运算的表达式
    $str = '12+5*2+3-5*2';
    //字符串的指针
    $index = 0;
    //声明一个用于组合联系数字的变量
    $keepNum = '';
    //定义一个数栈和一个符号栈
    $numsStack=new MyStack();
    $operStack=new MyStack();
    while (true)
    {
      $val = mb_substr($str,$index,1);
      //如果是一个符号就入符号栈 否则入数栈
      if ($operStack->isOper($val)==true)
      {
        //符号入栈前需要判断一下 栈为空直接入栈 不为空需要比较当前运算符与栈顶端的运算符
        //如果当前运算符的优先级低于栈内的 则需要运算
        if ($operStack->isEmpty())
        {
          $operStack->push($val);
        } else {
           while (!$operStack->isEmpty()&&$operStack->PRI($val)<=$operStack->PRI($operStack->getTop()))
           {
             //当前符号的优先级要直到高于栈内的时候才能入栈 否则要计算
            //当前运算符的优先级低于栈内的 则运算
            $num1 = $numsStack->pop();
            $num2 = $numsStack->pop();
            $oper = $operStack->pop();
            $res = $numsStack->getResult($num1,$num2,$oper);
            //计算完毕将结果入栈
            $numsStack->push($res);
           }
          //把当前这个符号再入符号栈
          $operStack->push($val);
            }
      } else {
        //考虑如果是连续数字的问题
        $keepNum.=$val;
        //先判断是否已经到字符串最后.如果已经到最后,就直接入栈.
        if ($index==mb_strlen($str)-1)
        {
          $numsStack->push($keepNum);//是数字直接入栈
        } else {
          //要判断一下$ch字符的下一个字符是数字还是符号.
          if ($operStack->isOper(mb_substr($str,$index+1,1)))
          {
            $numsStack->push($keepNum);
            $keepNum='';
          }
        }
      }
      $index++;//让$index指向下一个字符.
      if ($index==mb_strlen($str)) break;//已扫描到字符串的末尾 就退出while循环
   }
    /*
    4. 当扫描完毕后,就依次弹出数栈和符号栈的数据,并计算,最终留在数栈的值,就是运算结果,只有符号栈不空就一直计算
    */
    while (!$operStack->isEmpty())
    {
      $num1 = $numsStack->pop();
      $num2 = $numsStack->pop();
      $oper = $operStack->pop();
      $res = $numsStack->getResult($num1,$num2,$oper);
      //计算完毕将结果入栈
      $numsStack->push($res);
    }
//当退出while后,在数栈一定有一个数,这个数就是最后结果
echo $str.'='.$numsStack->getTop();
?>

PS:这里再为大家推荐几款计算工具供大家进一步参考借鉴:

在线一元函数(方程)求解计算工具:
http://tools.3water.com/jisuanqi/equ_jisuanqi

科学计算器在线使用_高级计算器在线计算:
http://tools.3water.com/jisuanqi/jsqkexue

在线计算器_标准计算器:
http://tools.3water.com/jisuanqi/jsq

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
使用Xdebug调试和优化PHP程序之[1]
Apr 17 PHP
PHP5中虚函数的实现方法分享
Apr 20 PHP
php unset全局变量运用问题的深入解析
Jun 17 PHP
新手菜鸟必读:session与cookie的区别
Aug 22 PHP
一组PHP可逆加密解密算法实例代码
Jan 21 PHP
PHP把小数转成整数3种方法
Jun 30 PHP
destoon实现首页显示供应、企业、资讯条数的方法
Jul 15 PHP
php验证手机号码
Nov 11 PHP
PHP中的表达式简述
May 29 PHP
php基于PDO连接MSSQL示例DEMO
Jul 13 PHP
php使用FFmpeg接口获取视频的播放时长、码率、缩略图以及创建时间
Nov 07 PHP
PHP中register_shutdown_function函数的基础介绍与用法详解
Nov 28 PHP
PHP操作MySQL中BLOB字段的方法示例【存储文本与图片】
Sep 15 #PHP
visual studio code 调试php方法(图文详解)
Sep 15 #PHP
PHP简单实现模拟登陆功能示例
Sep 15 #PHP
Thinkphp开发--集成极光推送
Sep 15 #PHP
php插件Xajax使用方法详解
Aug 31 #PHP
php数据库的增删改查 php与javascript之间的交互
Aug 31 #PHP
php注册系统和使用Xajax即时验证用户名是否被占用
Aug 31 #PHP
You might like
file_get_contents(&quot;php://input&quot;, &quot;r&quot;)实例介绍
2013/07/01 PHP
用js实现的仿sohu博客更换页面风格(简单版)
2007/03/22 Javascript
javascript 拖动表格行实现代码
2011/05/05 Javascript
Javascript图像处理—亮度对比度应用案例
2013/01/03 Javascript
JavaScript中的this关键字介绍与使用实例
2013/06/21 Javascript
JSON序列化与解析原生JS方法且IE6和chrome测试通过
2013/09/05 Javascript
javascript自定义右键弹出菜单实现方法
2015/05/25 Javascript
jquery对复选框(checkbox)的操作汇总
2016/01/13 Javascript
获取JS中网页各种高宽与位置的方法总结
2016/07/27 Javascript
node.js实现复制文本到剪切板的功能
2017/01/23 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
vue-image-crop基于Vue的移动端图片裁剪组件示例
2018/08/28 Javascript
JsonServer安装及启动过程图解
2020/02/28 Javascript
vue实现PC端分辨率适配操作
2020/08/03 Javascript
python对数组进行反转的方法
2015/05/20 Python
python计算圆周率pi的方法
2015/07/11 Python
Python实现输出程序执行进度百分比的方法
2017/09/16 Python
Python读取MRI并显示为灰度图像实例代码
2018/01/03 Python
学生信息管理系统python版
2018/10/17 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
python 字典访问的三种方法小结
2019/12/05 Python
windows下python安装pip方法详解
2020/02/10 Python
python实现按日期归档文件
2021/01/30 Python
CSS3新属性transition-property transform box-shadow实例学习
2013/06/06 HTML / CSS
美国最大的存储市场:SpareFoot
2018/07/23 全球购物
德国Discount-Apotheke中文官网:DC德式康线上药房
2020/02/18 全球购物
Herschel Supply Co.美国:背包、手提袋及配件
2020/11/24 全球购物
大学生的网上创业计划书
2013/12/31 职场文书
快餐店的创业计划书范文
2014/01/29 职场文书
《李时珍夜宿古寺》教学反思
2014/04/09 职场文书
地质工程专业毕业生求职信
2014/08/08 职场文书
租房协议书范例
2014/10/14 职场文书
租车协议书范本2014
2014/11/17 职场文书
2016年小学推普宣传周活动总结
2016/04/06 职场文书
导游词之贵州织金洞
2019/10/12 职场文书
go语言求任意类型切片的长度操作
2021/04/26 Golang