智能语音计算器(二)

这边文章来介绍该项目的计算引擎模块。

#ifndef CALCULATORDEC_H
#define CALCULATORDEC_H

#include <qt5/QtCore/QString>
#include <qt5/QtCore/QStack>
#include <qt5/QtCore/QString>
#include "ICalculator.h"

class CalculatorDec : public ICalculator
{
public:
    CalculatorDec();
    ~CalculatorDec();
    bool expression(const QString & exp);
    QString result();

private:
    QString calculate(const QString & exp);
    bool isDigit(char ch);
    bool isLeft(char ch);
    bool isDot(char ch);
    bool isRight(char ch);
    int judge(char c);
    double compute(char c,double a,double b);

private:
    QString m_exp;
    QString m_result;
};
#endif
    bool expression(const QString & exp);
    QString result();
这两个方法是重写 ICalculator中的方法,当然也可以通过别的方式实现,我在这是为了更好的理解Virtual函数的思想。
下面是该类的具体实现
#include "QCalculatorDec.h"

CalculatorDec::CalculatorDec()
{
    m_exp = "";
    m_result = "";
}

CalculatorDec::~CalculatorDec()
{

}

bool CalculatorDec::expression(const QString & exp)
{
    bool ret = false;

    m_result = calculate(exp);
    ret = (m_result != "Error");

    return ret;
}

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

QString CalculatorDec::calculate(const QString & exp)
{
    
    QString ret = "Error";
    QByteArray ba = exp.toLatin1();
    const char *str = ba.data();
    QStack<double> stack_digit;
    QStack<char> stack_op;
    const char *p;
    for(p=str;*p;p++)
    {
       
        if(isDigit(*p))
        {
            stack_digit.push(atof(p));
            while(isDigit(*p)) p++;
            if(isDot(*p))
            {
                p=p+1;
                while(isDigit(*p)) p++;
            }
            p--;
           // printf("%c\n",*p);
        }
        else
        {
            if(stack_op.isEmpty() || isLeft(*p))
            {
                stack_op.push(*p);
                continue;
            }
            else
            {
                if(isRight(*p))
                {
                    while(!isLeft(stack_op.top()))
                    {
                        char b1 = stack_op.pop();
                        double a1 = stack_digit.pop();
                        double a2 = stack_digit.pop();
                        stack_digit.push(compute(b1,a1,a2));
                    }
                    stack_op.pop();
                }
                else
                {
                    if(!isLeft(stack_op.top()))
                    {
                        if(judge(*p)<=judge(stack_op.top()))
                        {
                            char b2 = stack_op.pop();
                            double a3 = stack_digit.pop();
                            double a4 = stack_digit.pop();
                            stack_digit.push(compute(b2,a3,a4));
                            p--;
                            continue;
                        }
                        else
                        {
                            stack_op.push(*p);
                        }
                    }
                    else
                    {
                        stack_op.push(*p);
                    }
                }
            }
        }
    }
    while(!stack_op.isEmpty())
    {
        char b3 = stack_op.pop();
        double a5 = stack_digit.pop();
        double a6 = stack_digit.pop();
        stack_digit.push(compute(b3,a5,a6));
    }
    double ret1 = stack_digit.pop();
    ret = QString::number(ret1,'f',2);
    return ret;
}

bool CalculatorDec::isDigit(char ch)
{
    if(ch>='0' && ch<='9')  return true;
    else return false;
}

bool CalculatorDec::isLeft(char ch)
{
    if(ch=='(') return true;
    else return false;
}

bool CalculatorDec::isDot(char ch)
{
    if(ch=='.')   return true;
    else return false;
}

bool CalculatorDec::isRight(char ch)
{
    if(ch==')') return true;
    else return false;
}

int CalculatorDec::judge(char c)
{
    int ret = 0;
    if(c=='+' || c=='-')
        ret = -1;
    if(c=='*' || c=='/')
        ret = 0;
    return ret;
}

double CalculatorDec::compute(char c,double a,double b)
{
    double ret = 0;
    if(c=='+')  ret = b+a;
    if(c=='-')  ret = b-a;
    if(c=='*')  ret = b*a;
    if(c=='/')  ret = b/a;
    return ret;
}

 

说一下算法设计思路,首先是用两个栈来存放数据和符号(数据栈和符号栈)。

算法(重点):

数字:数字无条件入栈
符号:
判断符号栈是否为空,如果为空,则无条件入栈
如果不为空,

当前符号如果为右括号:
一直去弹符号栈,直到弹出第一个左括号。

当前符号如果不为右括号: 
判读栈顶元素是不是左括号
栈顶不是左括号 
当前符号优先级 <= 栈顶元素的优先级,则计算。(出栈一个符号,出两个数字,先出栈的数字是右操作数,后出栈的数字是左操作数)
当前符号优先级 > 栈顶元素的优先级,符号入栈。

栈顶是左括号
当前符号无条件入栈

循环结束:
判断符号栈是否为空,如果为空,则数据栈的栈顶元素,就是最后的结果。
如果不空,一直计算,直到符号栈为空。

转载于:https://www.cnblogs.com/wzqstudy/p/10076610.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自1.6版以后,增加了表达式计算的功能,从此可以进行复杂的公式计算,如输入以下公式“2+(18-10)/7^2+sin(1)+sqrt(sqrt(5),3)*2”,按下计算按钮或回车会自动得出最终结果。另外增加了一个“单步求解”的选项,可以一步一步显示出公式的计算过程。支持各种三角函数,运算的结果可选择弧度或角度值,这取决于计算器的角度|弧度按钮选择。打开表达式计算的功能步骤是:鼠标右键单击液晶屏幕,在弹出的菜单中选择“* 表达式(公式)计算 *”一项,即可打开该功能。(注:表达式功能不能在小窗口状态下使用),另外,v1.6版还改进了许多以前版本中不方便或有BUG的地方,使用更加方便!增加了十几种三角函数运算(包括各种双曲正弦、余弦、正割、余割等等以及相关反函数),加入了角度与弧度计算,加入了位移指令,增加了各种常用常数表,使用户在计算一些常用公式时,不必再去翻书查找。加入了各种单位换算,单位换算与屏幕计算结果实时换算,并可实时改变换算单位。并修改了数据转换为"人民币中文大写形式、人民币数字形式(例如:1435.75、人民币壹仟肆佰叁拾伍圆柒角伍分、¥1435.75)的一些BUG,大大方便了财务、票据等方面的工作,输入的任何数据和计算结果可自动输入在其它程序窗口当前光标位置,就像和其它程序融为一体一样。如果用户经常在应用软件中做计算输入工作(例如各种文字处理、制表、工程计算、股票等等一切需要输入计算数据和结果的地方。),那么这个功能将使工作变得非常方便!(如果不需要这项功能,鼠标右键单击液晶屏幕,在弹出的菜单中取消“数据自动输入其它窗口”一项即可!)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值