树莓派4B与Android之缘(十):Android应用科学计算器开发(3)运算原理、calculator类与basecalculator类

一、运算原理

计算器类有Calculator类、BaseCalculator类、ScienceCalculator类。Calculator类用来表示计算器的状态。BaseCalculator类用来运算基本数学表达式(+ - X / 操作,其中还有E运算,用来运算2E(-16)这种小数的运算,或者3E(15)这种超大数运算 ),ScienceCalculator类用来完成科学运算,进行如sin、cos、tan等的运算,并将科学数学表达式转换为基本运算器BaseCalculator类可以完成的基本数学表达式

二、calculator类

1.作用

此类用来表示当前计算器的状态,如是否有新的运算式,是否为科学模式,是否为弧度制

2.原理

(1)中缀表达式转后缀表达式

  1. 初始化两个栈:运算符栈s1和储存后缀表达式的队列s2; 从左至右扫描中缀表达式; 遇到操作数时,将其压入s2;
  2. 遇到运算符时,比较其与s1栈顶运算符的优先级: 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
  3. 否则,若优先级比栈顶运算符的高,也将运算符压入s1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
  4. 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较; 遇到括号时:
  5. 如果是左括号“(”,则直接压入s1;
  6. 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃;
  7. 重复步骤2至5,直到表达式的最右边; 将s1中剩余的运算符依次弹出并压入s2;
  8. 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)

(2)运算后缀表达式

  1. 从左到右扫描后缀表达式,如果是操作数,就压入操作数栈s3,如果是操作符,就连续弹出两个操作数(注意:后弹出的为第一操作数,先弹出的为第二操作数),然后进行操作符的操作,将新生成的操作数压入栈中,反复直到后缀表达式扫面完毕,栈s3中只存在一个数,就是最终结果

2.代码

public class Calculator {
    //是否为科学模式
    private boolean isScientific=false;
    //是否为新运算式
    private boolean isNew=true;
    //是否为弧度制
    private boolean isRad=true;
    public boolean isScientific() {
        return isScientific;
    }

    public void setScientific(boolean scientific) {
        isScientific = scientific;
    }

    public boolean isNew() {
        return isNew;
    }

    public void setNew(boolean aNew) {
        isNew = aNew;
    }

    public boolean isRad() {
        return isRad;
    }

    public void setRad(boolean rad) {
        isRad = rad;
    }
}

二、BaseCalculator类

1.作用

此类用于实现+ - x / E运算

2.代码实现

package com.example.calculator.model;


import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;

public class BaseCalculator {
	//用来存取数和运算符
    private class Ele {
        public boolean isNum;
        public double o;
        public char op;
        public Ele(double o,boolean isNum){
            this.isNum=isNum;
            this.o=o;
        }

        public Ele(char op,boolean isNum) {
            this.isNum = isNum;
            this.op = op;
        }
    }

    //Map结构方便后面取运算符的优先级
    private final Map<Character, Integer> operMap = new HashMap<Character, Integer>() {{
        put('+', 0);
        put('-', 0);
        put('×', 1);
        put('/', 1);
        put('E', 2);
        put('(', 3);
        put(')', 3);
    }};

    //简单四则运算
    private double operate(double a, char oper, double b) {
        switch (oper) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '×':
                return a * b;
            case '/':
                if (b == 0) {
                    return Double.MAX_VALUE; //处理异常
                }
                return a / b;
            case 'E':
                return Double.parseDouble(String.valueOf(a+"E"+(int)b));
            default:
                return 0;
        }
    }
    //计算
    public double cal(String math) {
        if (math.length() == 0) {
            return Double.MAX_VALUE;
        } else {
            Stack<Character> operStack = new Stack<>(); //oper栈
            Queue<Ele> eleQueue = new LinkedList<>();
            Stack<Double> numStack = new Stack<>();

            //中缀变后缀
            int firstIndex = 0;
            int i=0;
            while (i < math.length()) {
                char charOfMath = math.charAt(i);
                if (charOfMath == '(') {
                    operStack.push(charOfMath);
                    i++;
                } else if (charOfMath == ')') {
                    while (operStack.peek() != '(') {
                        eleQueue.offer(new Ele(operStack.pop(), false));
                    }
                    operStack.pop();
                    i++;
                }else if(isNum(charOfMath)){
                    firstIndex=i;
                    while (++i<math.length()&&isNum(math.charAt(i)));
                    double num;
                    try {
                        num = Double.parseDouble(math.substring(firstIndex, i));
                    } catch (NumberFormatException e) {
                        return Double.MAX_VALUE;
                    }
                    eleQueue.offer(new Ele(num,true));
                }else{
                    //说明-是单目运算符
                    if (charOfMath == '-') {
                        if (i == 0) {
                            firstIndex=0;
                            while (++i<math.length()&&isNum(math.charAt(i)));
                            double num;
                            try {
                                num = Double.parseDouble(math.substring(firstIndex, i));
                            } catch (NumberFormatException e) {
                                return Double.MAX_VALUE;
                            }
                            eleQueue.offer(new Ele(num,true));
                            continue;
                        } else if (math.charAt(i - 1)=='(') {
                            //表示这是一个单目运算符
                            firstIndex=i;
                            while (++i<math.length()&&isNum(math.charAt(i)));
                            double num;
                            try {
                                num = Double.parseDouble(math.substring(firstIndex, i));
                            } catch (NumberFormatException e) {
                                return Double.MAX_VALUE;
                            }
                            eleQueue.offer(new Ele(num,true));
                            continue;
                        }


                    }
                    while (operStack.size() >= 0) {
                        if (operStack.size() == 0 || operStack.peek() == '(') {
                            operStack.push(charOfMath);
                            break;
                        } else {
                            if (operMap.get(operStack.peek()) < operMap.get(charOfMath)) {
                                operStack.push(charOfMath);
                                break;
                            } else {
                                eleQueue.offer(new Ele(operStack.pop(), false));
                            }
                        }
                    }
                    i++;
                }
            }
            //将剩余操作符压入后缀表达式
            while (operStack.size()>0){
                eleQueue.offer(new Ele(operStack.pop(),false));
            }
            //检查后缀并运算
            while (eleQueue.size() > 0) {
                if (eleQueue.element().isNum) {
                    numStack.push(eleQueue.poll().o);
                } else {
                    char op = eleQueue.poll().op;
                    double second= numStack.pop();
                    double first = numStack.pop();
                    numStack.push(operate(first, op, second));
                }
            }
            return numStack.peek();
        }
    }

    private boolean isNum(char c){
        return (c-'0'>=0&&c-'0'<=9)||c=='.';
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值