计算器核心算法解析下

遍历后缀表达式中的数字和运算符

当前元素为数字:进栈

当前元素为运算符:

1.从栈中弹出右操作数

2.从栈中染出左操作数

3.根据符号进行运算

4.将运算结果压入栈中

遍历结束

栈中的唯一数字为于是暖结果

while(!exo,isEmpty())

{

	if(当前元素为数字)

	入栈;

	else if(当前元素为运算符)

	{

		1.操你个栈中弹出右操作数;

		2.从栈中染出左操作数;

		3.根据符号进行运算;

		4.将原酸结果压入栈中

	}

	else

		表达式错误;

}
注意
-数学计算相关的算法都需要考虑除0操作
若是浮点运算,避免代码中直接与0做相等比较
const double p = 0.00000000000000001;
if(-p < r)&& (r < p)
{
	ret = "Error";
}
else
{
	ret.sprintf("%f", l/r);
}
#include "QCalculatorDec.h"

QCalculatorDec::QCalculatorDec()
{
    m_exp = "";
    m_result = "";


}

QCalculatorDec::~QCalculatorDec()
{

}

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

bool QCalculatorDec::isSymbol(QChar c)//操作符+ 0*
{
    return isOperator(c) || (c == '(') || (c == ')');
}

bool QCalculatorDec::isSign(QChar c)//是不是正负号
{
    return (c == '+') || (c == '-');
}

bool QCalculatorDec::isNumber(QString s)//合法的数字
{
    bool  ret = false;
    s.toDouble(&ret);
    return ret;
}

bool QCalculatorDec::isOperator(QString s)//四则运算符
{
    return (s == "+") || (s == "-") || (s == "*") || (s == "/");
}

bool QCalculatorDec::isLeft(QString s)
{
    return (s == "(");
}

bool QCalculatorDec::isRight(QString s)
{
    return (s == ")");
}

int QCalculatorDec::priority(QString s)//返回优先级
{
    int ret = 0;

    if((s == "+") || (s == "-"))
    {
        ret = 1;
    }

    if((s == "*") || (s =="/"))
    {
        ret = 2;
    }

    return ret;
}

bool QCalculatorDec::expression(const QString& exp)
{
    bool ret = false;
    QQueue<QString> spExp = split(exp);//先分离
    QQueue<QString> postExp;

    m_exp = exp;//保存至内成员中

    if(transform(spExp, postExp))//中缀转后缀
    {
        m_result = calculate(postExp);
        ret = (m_result != "Error");
    }
    else {
        m_result = "Error";
    }


    return ret;
}

QString  QCalculatorDec::result()
{
    return m_result;
}

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;
}

bool QCalculatorDec::match(QQueue<QString>& exp)//匹配算法
{
    bool ret = true;
    int len = exp.length();
    QStack<QString> stack;

    for(int i = 0; i < len; i++)
    {
        if(isLeft(exp[i]) )
        {
            stack.push(exp[i]);
        }
        else if(isRight(exp[i]))
        {
            if(!stack.isEmpty() && isLeft(stack.top()))
            {
                stack.pop();
            }
            else
            {
                ret = false;
                break;
            }
        }

    }

    return ret;
}

bool QCalculatorDec::transform(QQueue<QString>& exp, QQueue<QString>& output)//中缀转后缀
{
    bool ret = match(exp);
    QStack<QString> stack;

    output.clear();//输出清空
    while( ret && !exp.isEmpty())
    {
        QString e = exp.dequeue();

        if(isNumber(e))
        {
            output.enqueue(e);
        }
        else if(isOperator(e))
        {
            while(!stack.isEmpty() && (priority(e) <= priority(stack.top())))
            {
                output.enqueue(stack.pop());
            }
            stack.push(e);
        }
        else if(isLeft(e))
        {
            stack.push(e);
        }
        else if(isRight(e))
        {
            while(!stack.isEmpty() &&  !isLeft(stack.top()))
            {
                output.enqueue(stack.pop());
            }
            if(!stack.isEmpty())
            {
                stack.pop();
            }
        }
        else
        {
            ret = false;
        }
    }

    while(!stack.isEmpty())
    {
        output.enqueue(stack.pop());
    }

    if(!ret)
    {
        output.clear();
    }

    return ret;
}

QString QCalculatorDec::calculate(QString l, QString op, QString r)//左右操作数,操作符
{
    QString ret = "Error";
    if(isNumber(l) && isNumber(r))
    {
        double lp =  l.toDouble();
        double rp = r.toDouble();

        if(op == "+")
        {
            ret.sprintf("%f", lp + rp);
        }
        else if(op == "-")
        {
            ret.sprintf("%f", lp - rp);
        }
        else if(op == "*")
        {
            ret.sprintf("%f", lp *rp);
        }
        else if(op == "/")
        {
            const double p = 0.000000000000001;
            if((-p < rp) && (rp < p) )
            {
                ret = "Error";
            }
            else {
                ret.sprintf("%f", lp / rp);
            }
        }
        else {
            ret = "Error";
        }
    }

    return ret;
}

QString QCalculatorDec::calculate(QQueue<QString>& exp)//函数计算
{
    QString ret =  "Error";
    QStack<QString> stack;

    while(!exp.isEmpty())
    {
        QString e = exp.dequeue();//从队列头部取出来
        if(isNumber(e))//数字
        {
            stack.push(e);
        }
        else if(isOperator(e))//运算符
        {
            QString rp = !stack.isEmpty() ? stack.pop() : "";
            QString lp = !stack.isEmpty() ? stack.pop() : "";
            QString result = calculate(lp, e, rp);

            if(result != "Error")
            {
                stack.push(result);
            }
            else
            {
                break;
            }
        }
        else {
            break;
        }
    }

    if(exp.isEmpty() && (stack.size() == 1) && isNumber(stack.top()))
    {
        ret = stack.pop();
    }

    return ret;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值