ホームページ  >  記事  >  バックエンド開発  >  高機能電卓を実装したPHPの関数例(スタックベース)

高機能電卓を実装したPHPの関数例(スタックベース)

黄舟
黄舟オリジナル
2017-09-16 09:14:101864ブラウズ

この記事では主に、PHP スタックに基づいて実装された高度な計算機関数を紹介します。これには、PHP スタックの定義と、スタックを使用して数値演算を実行するための関連操作テクニックが含まれます。この記事では、スタックに基づく PHP の実装について説明しています。高度な電卓機能。参考のために皆さんと共有してください。詳細は次のとおりです。

文字列演算式を取得したとき、その演算結果をどのように取得するのでしょうか?

現時点では、スタック アルゴリズムを使用して、この問題を非常に賢く解決できます。

アイデアは次のとおりです: (PHP 関数 substr ループを使用してこの文字列操作式をインターセプトし、この文字列の値を順番に取り出します [最初の文字からインターセプトする必要があります]。インターセプトの開始位置を次のように設定します。ループ 成長する変数は [$index=0] に初期化されます) 同時に、数値を格納するスタック [$numStack] と演算子を格納するスタック [$operStack] も 1 つ作成する必要があります。演算記号かどうかを判定できる関数で、切り取った各値をこのカスタム関数に入れて、数値か演算子か区別できる識別子を返すことで、値が数値か演算子かを判定します。演算子である場合は、数値スタックに挿入されます。演算子の場合は、シンボル スタックが挿入されます。数値スタックを挿入する場合は、直接挿入できますが、シンボル スタックには特別な処理が必要です [[シンボル スタックが空の場合は、空ではなく直接挿入します。挿入されたシンボルの操作の優先順位をシンボルと比較する必要があります。スタック内 (シンボルの優先順位を決定する関数を定義できます。* と / は 1 であると仮定し、+ と - は 0 であると仮定します。演算子の優先順位を取得できるように、数値が大きいほど優先順位が高いと仮定します)。挿入されるシンボルの優先順位は以下です。スタックの先頭にある演算子の優先順位は数値スタックから 2 つの値をポップし、それらを操作するためにシンボル スタックから演算子をポップします。

以下は PHP の例です [ハン シュンピン先生の PHP アルゴリズム チュートリアルを参照してください]

<html>
<head>
<meta http-equiv=&#39;content-type&#39; content=&#39;text/html;charset=utf-8&#39;/>
</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 &#39;<br/>栈满,不能添加&#39;;
          return;
        }
        $this->top++;
        $this->stack[$this->top]=$val;
      }
      //出栈的操作,就是把栈顶的值取出
      public function pop()
      {
        //判断是否栈空
        if($this->top==-1){
          echo &#39;<br/>栈空1&#39;;
          return;
        }
        //把栈顶的值,取出
        $topVal=$this->stack[$this->top];
        $this->top--;
        return $topVal;
      }
      //显示栈的所有数据的方法.
      public function showStack()
      {
        if($this->top==-1){
          echo &#39;<br/>栈空2&#39;;
          return;
        }
        echo &#39;<br/>当前栈的情况是....&#39;;
        for($i=$this->top;$i>-1;$i--){
          echo &#39;<br/> stack[&#39;.$i.&#39;]=&#39;.$this->stack[$i];
        }
      }
      //判断是否是一个运算符
      public function isOper($val)
      {
        if ($val==&#39;+&#39;||$val==&#39;-&#39;||$val==&#39;*&#39;||$val==&#39;/&#39;)
        {
          return true;
        }
      }
      //判断栈是否为空
      public function isEmpty()
      {
        if ($this->top==-1) return true;
      }
      /**
       * 比较运算符的优先级
       * 我把 * 和/运算符的优先级看作1
       * +和- 看作0
       * 通过它们之间的比较就能得出它们的优先级谁更高
       */
      public function PRI($oper)
      {
        if ($oper==&#39;*&#39;||$oper==&#39;/&#39;)
        {
          return 1;
        } else if ($oper==&#39;+&#39;||$oper==&#39;-&#39;) {
          return 0;
        }
      }
      //返回栈顶端的值
      public function getTop()
      {
        return $this->stack[$this->top];
      }
      //计算
      public function getResult($num1,$num2,$oper)
      {
        switch ($oper)
        {
          case &#39;+&#39;:
            $res = $num2+$num1;
          break;
          case &#39;-&#39;:
            $res = $num2-$num1;
          break;
          case &#39;*&#39;:
            $res = $num2*$num1;
          break;
          case &#39;/&#39;:
            $res = $num2/$num1;
          break;
        }
        return $res;
      }
    }
    //需要进行运算的表达式
    $str = &#39;12+5*2+3-5*2&#39;;
    //字符串的指针
    $index = 0;
    //声明一个用于组合联系数字的变量
    $keepNum = &#39;&#39;;
    //定义一个数栈和一个符号栈
    $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=&#39;&#39;;
          }
        }
      }
      $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.&#39;=&#39;.$numsStack->getTop();
?>

以上が高機能電卓を実装したPHPの関数例(スタックベース)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。