计算器核心解析算法

1 计算器核心解析算法

1.1 计算器核心解析算法概述

计算机如何读懂四则运算表达式呢?
在这里插入图片描述
后缀表达式:

  • 人类习惯的数学表达式叫做中缀表达式。
  • 另外,还有一种将运算符放在数字后面的后缀表达式。
  • 实例:
    在这里插入图片描述
    中缀和后缀表达式:
  • 中缀表达式符合人类的阅读和思维习惯。
  • 后缀表达式符合计算机的运算方式:
    • 消除了中缀表达式中的括号。
    • 同时保留中缀表达式中的运算优先级。

计算机核心算法的解决方案如下:

  1. 将中缀表达式进行数字和运算符的分离。
  2. 将中缀表达式转换为后缀表达式。
  3. 通过后缀表达式计算最终结果。

1.2 分离算法分析

索要计算的中缀表达式中包含:

  • 数字和小数点【0-9或.】
  • 符号位【+或-】
  • 运算符【+,-,*,/】
  • 括号【(或)】

思想:以符号作为标志对表达式中的字符逐个访问。
在这里插入图片描述
在这里插入图片描述

难点:如何区分正负号与加号和减号?

  • +和-在表达式的第一个位置。
  • 括号后的+和-。
  • 运算符后的+和-。
    在这里插入图片描述
    具体实现放在QCalculatorDec类中,代码如下:
    QCalculatorDec.h:
#ifndef _CALCULATORCORE_H_
#define _CALCULATORCORE_H_

#include <QString>
#include <QStack>
#include <QQueue>

class QCalculatorDec
{
   
   
protected:
    bool isDigitOrDot(QChar c);
    bool isSymbol(QChar c);
    bool isSign(QChar c);
    bool isOperator(QString s);
    QQueue<QString> split(const QString& exp);
public:
    QCalculatorDec();
    ~QCalculatorDec();
};

#endif

QCalculatorDec.cpp:

#include "QCalculatorDec.h"

#include <QDebug>

QCalculatorDec::QCalculatorDec()
{
   
   
    QQueue<QString> r = split("+9.11 + ( -3 - 1 ) * -5 ");

    for(int i=0; i<r.length(); i++)
    {
   
   
        qDebug() << r[i];
    }
}

QCalculatorDec::~QCalculatorDec()
{
   
   

}

bool QCalculatorDec::isDigitOrDot(QChar c)
{
   
   
    return (('0' <= c) && (c <= '9')) || (c == '.');
}

bool QCalculatorDec::isSymbol(QChar c)
{
   
   
    return isOperator(c) || (c == '(') || (c == ')');
}

bool QCalculatorDec::isSign(QChar c)
{
   
   
    return (c == '+') || (c == '-');
}

bool QCalculatorDec::isOperator(QString s)
{
   
   
    return (s == "+") || (s == "-") || (s == "*") || (s == "/");
}

QQueue<QString> QCalculatorDec::split(const QString& exp)
{
   
   
    QQueue<QString> ret;
    QString num = "";
    QString pre = "";

    for(int i=0; i<exp.length(); i++)
    {
   
   
        if( isDigitOrDot(exp[i]) )
        {
   
   
            num += exp[i];
            pre = exp[i];
        }
        else if( isSymbol(exp[i]) )
        {
   
   
            if( !num.isEmpty() )
            {
   
   
                ret.enqueue(num);

                num.clear();
            }

            if( isSign(exp[i]) && ((pre == "") || (pre == "(") || isOperator(pre)) )
            {
   
   
                num += exp[i];
            }
            else
            {
   
   
                ret.enqueue(exp[i]);
            }

            pre = exp[i];
        }
    }

    if( !num.isEmpty() )
    {
   
   
        ret.enqueue(num);
    }

    return ret;
}

1.3 中缀转后缀算法分析

中缀表达式转后缀表达式的过程类似编译过程:

  • 四则运算表达式中的括号必须匹配。
  • 根据运算符优先级进行转换。
  • 转换后的表达式中没有括号。
  • 转换后可以顺序的计算出最终结果。

中缀转后缀的过程如下:
在这里插入图片描述
在这里插入图片描述
关键点:转换过程中左右括号是重要标志

  • 如何确保表达式中的括号能够左右匹配?

括号匹配算法:
在这里插入图片描述
实现代码如下:
QCalculatorDec.h:

#ifndef _CALCULATORCORE_H_
#define _CALCULATORCORE_H_

#include <QString>
#include <QStack>
#include <QQueue>

class QCalculatorDec
{
   
   
protected:
    QString m_exp;
    QString m_result;

    bool isDigitOrDot(QChar c);
    bool isSymbol(QChar c);
    bool isSign(QChar c);
    bool isNumber(QString s);
    bool isOperator(QString s);
    bool isLeft(QString s);
    bool isRight(QString s);
    int priority(QString s);
    bool match(QQueue<QString>& exp);
    bool transform(QQueue<QString>& exp, QQueue<QString>& output);
    QQueue<QString> split(const QString& exp);
public:
    QCalculatorDec();
    ~QCalculatorDec();
    bool expression(const QString& exp)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值