1. 计算器类
整体框架采用面向对象的方法,计算方法采用“算符优先算法”和“后缀表达式算法”。
定义一个计算器类。利用计算器类的实例化对象调用类中定义的运算方法以实现表达式的计算。
class Calculator
{
public:
Calculator();
void getFormat(); //表达式自定义标准格式化
int getPrior(char c); //获取算术符号优先级
void getPostfix(); //后缀表达式转换
void calResult(); //计算结果
void calculate(); //计算方法
double getResult(); //获取结果
string operatorSym; //运算符号
string infix; //表达式缓存
private:
vector<string> postfix; //后缀表达式向量
stack<char> symStack; //符号栈
stack<double> figStack; //数字栈
string stdInfix; //自定义标准格式化表达式
double result; //最终计算结果
};
整个计算方法大体划分为3个模块,实现一个总的计算方法,用来调用相关计算模块。
//计算方法
void Calculator::calculate(string infix) {
getFormat(infix); //表达式自定义标准格式化
getPostfix(); //后缀表达式转换
calResult(); //计算结果
}
1 功能实现
- 符号功能实现
a) ‘+’、‘-’、‘*’、‘/’:加减乘除运算。
b) ‘^’:幂次方运算。
c) “( )、 [ ] 、{ }”:三种括号的实现。
- 数字功能实现
a) 0~9。
b) 小数运算。
c) 正负数运算。
2 运算优先级功能实现
运算的规则和顺序由运算符的优先级关系确定,这是运算的核心,因此首先必须明确符号之间的优先级关系。
- 基本符号优先级:
5个优先级分别对应0~3。
enum PRIO_LV {
PRIO_LV0 = 0,
PRIO_LV1 = 1,
PRIO_LV2 = 2,
PRIO_LV3 = 3,
};
获取符号优先级函数,用于转换后缀表达式时对符号优先级的比较。
//获取算术符号优先级
int Calculator::getPrior(char c) {
if (c == '+' || c == '-') {
return PRIO_LV1;
}
else if (c == '*' || c == '/') {
return PRIO_LV2;
}
else if (c == '%' || c == '^' || c == '~') {
return PRIO_LV3;
}
else {
return PRIO_LV0;
}
//else { cout << c << 非法符号! << endl; }
}
- 括号型符号优先级:
( )、[ ]、{ } 括号型,左括号优先级再、在所有符号中为最低优先级,右括号为最高优先级。4种括号型暂无相对优先级,为同等优先级。
1 构造函数,初始化成员变量
Calculator::Calculator() {
result = 0.0;
cal_ErrorImfo = "";
}
2 正负数格式化模块
该模块用来实现表达式的正负数形式。通过在正负数的‘+’或‘-’符号前加一个0实现,以便于整个表达式的计算。即:-x转换为0-x,+x转化为0+x。
//表达式自定义标准格式化
void Calculator::getFormat() {
stdInfix = infix;
//实现正负数
for (size_t i = 0; i < stdInfix.size(); i++) { //string.size()返回size_type类型,避免下标运算时的类型溢出
if (stdInfix[i] == '-' || stdInfix[i] == '+') { //-x转换为0-x,+x转化为0+x
if (i == 0) {
stdInfix.insert(0, 1, '0');
}
else if (stdInfix[i - 1] == '(') {
stdInfix.insert(i, 1, '0');
}
}
}
}
3 后缀表达式转换
计算机处理中缀表达式的计算比较复杂,应转换为前缀或后缀表达式。该程序改用后缀表达式法,利用定义的符号栈按照算术符号的优先级来做中缀表达式到后缀表达式的转换。
转换如下:
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要用到栈,具体过程如下:
1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
4 计算后缀表达式
遍历后缀表达式,创建数字栈,是数字则入栈,是算术符号则出栈响应的数字个数并利用相应的符号计算得出结果数后,将该结果数入栈,以此循环直到后缀表达式遍历完成,栈中最后一个数即为最终结果。
2. 复数类
建立Complex类, 并根据复数加减乘除规则进行了操作符的重写
class Complex {
private:
float Real, Imag;
public:
Complex(float r = 0, float i = 0) {
Real = r;
Imag = i;
}
//显示输出复数
void show() {
cout << Real << "+" << Imag << "i";
}
Complex operator +(Complex& c);//"+"运算符重载完成复数间的加法运算
Complex operator +(float s);//"+"完成实部与实数的加法运算
Complex operator -(Complex& c);
Complex operator -(float s);
Complex operator *(Complex& c);
Complex operator *(float s);
Complex operator /(Complex& c);
Complex operator / (float s);
Complex conj(void);
};
Complex Complex::operator +(float s) {
Complex t;
t.Real = Real + s;
t.Imag = Imag;
return t;
}
Complex Complex::operator-(Complex& c) {
Complex t;
t.Real = Real - c.Real;
t.Imag = Imag - c.Imag;
return t;
}
Complex Complex::operator-(float s) {
Complex t;
t.Real = Real + s;
t.Imag = Imag - s;
return t;
}
Complex Complex::operator *(Complex& c) {
Complex t;
t.Real = Real * c.Real - Imag * c.Imag;
t.Imag = Real * c.Imag + Imag * c.Real;
return t;
}
Complex Complex::operator *(float s) {
Complex t;
t.Real = Real * s;
t.Imag = Imag * s;
return t;
}
Complex Complex::operator /(Complex& c) {
Complex t;
if (c.Real != 0 && c.Imag != 0) {
t.Real = (Real * c.Real + Imag * c.Imag) / (c.Real * c.Real + c.Imag * c.Imag); //实部除积
t.Imag = (Imag * c.Real - Real * c.Imag) / (c.Real * c.Real + c.Imag * c.Imag); //虚部除积
return t;
}
else {
cout << "分母为0,不能执行命令";
return -1;
}
}
Complex Complex::operator /(float s) {
Complex t;
if (s != 0.0) {
t.Real = Real / s;
t.Imag = Imag / s;
return t;
}
else {
cout << "分母为0,不能执行命令";
return -1;
}
}
Complex Complex::conj(void) {
Complex t;
t.Real = Real;
t.Imag = -Imag;
return t;
}
3. 主函数
通过用户输入来控制进行实数域的计算还是复数域的计算, 分别调用相应的语句执行相关计算
cout << "欢迎来到高性能计算器!" << endl;
Calculator cal;
while (true) {
cout << "实数运算输入1, 复数运算输入2" << endl;
int choice = 1;
cin >> choice;
cin.ignore(); // 清除换行符
if (choice == 1) {
cout << cal.operatorSym << endl;
cout << "-----------------------" << endl;
getline(cin, cal.infix);
cal.calculate();
cout << cal.getResult() << endl;
cout << "-----------------------" << endl;
}
if (choice == 2)
{
cout << "虚数运算部分:" << endl;
cout << "-----------------------" << endl;
float a, b, c, d;
cout << "请输入第一个复数的实部与虚部:";
cin >> a >> b;
cout << "请输入第二个复数的实部与虚部:";
cin >> c >> d;
Complex A(a, b), B(c, d), C, D, E, F, G, H;
C = A + B, D = A - B, E = A * B, F = A / B, G = A.conj(), H = B.conj();
cout << "加法:"; A.show(); cout << "+"; B.show(); cout << "="; C.show(); cout << endl;
cout << "减法:"; A.show(); cout << "-"; B.show(); cout << "="; D.show(); cout << endl;
cout << "乘法:("; A.show(); cout << ")*("; B.show(); cout << ")="; E.show(); cout << endl;
cout << "除法:("; A.show(); cout << ")/("; B.show(); cout << ")="; F.show(); cout << endl;
cout << "-----------------------" << endl;
}
}
return 0;
cout << "减法:"; A.show(); cout << "-"; B.show(); cout << "="; D.show(); cout << endl;
cout << "乘法:("; A.show(); cout << ")*("; B.show(); cout << ")="; E.show(); cout << endl;
cout << "除法:("; A.show(); cout << ")/("; B.show(); cout << ")="; F.show(); cout << endl;
cout << "-----------------------" << endl;
}
}
return 0;