当前位置: 首页 > news >正文

Android学习之计算器app(java + 详细注释 + 源码)

运行结果:

基础的四则运算:

可能会出现的问题以及解决方法:

 问题1:出现多个操作符。

例子:1++++++2

解决方法:

在用户点击操作符之后,去检查之前的最后一位,如果最后一位也是操作符的话,就进行替代操作。

问题2:小数点问题。

例子:0......1  以及 .2

解决方法:

对于0.....1的问题,用的是一个全局变量 addPoint,当它为true的时候才可以进行添加小数点操作。

当点击 π 或者是 小数点之后 就要把 addPoint 置为false,也即表示不能再去添加小数点了。

当点击操作符或者是C(清空)之后就要把 addPoint 置为false,也即表示可以再去添加小数点了。

问题3:非法操作。

例子:

1:除0

2:阶乘溢出

3:负数开根号

4:logx, 其中x <= 0

5:(0.123)!

6:(-3)!

解决方法:

对每个运算进行提前监控,如果出现违规操作要把用户的除了C(清空)按钮外全部禁掉,然后做出违规提示,参考Win11自带计算器。但是感觉更加规范的是 可以自定义异常 然后去对应到每一个的异常处理问题。

问题4:负数的复杂性

例子:-3 对这个实现起来还是比较麻烦的

解决方法:

对这个不进行特殊判断,还是点击 "-" 之后看看它的前面有没有数字,如果没有的话,也去补上0, 这个0是默认的。

新增括号功能:

对括号进行了显示,以及可以进行括号运算

在界面显示出右括号和左括号的数量,而且右括号的数量数不能多于左括号的,参照win11自带计算器。

可能出现的问题以及解决方法:

问题1:出现 (+)。

也即是括号里面只有操作符。

解决的方法:

1:当点击运算符的时候,检查它的前面是不是 "(", 如果是的话就去自动去补0

2:当点击 "(" 的时候,去检查它的前面是不是 操作符,如果是的话就去自动补0

问题2:出现(0)(0)这样的情况。
解决方法:

当用户点击 "(" 的时候去校验当前已经存在的字符串的最后一位,如果它不是操作符的话,就去指定去补上一个操作符,我在这里默认的是 "x"。

问题3:出现0 + (-3) + 5 这样的情况。
解决方法:

当用户点击操作符的时候,就去检测当前已经存在的最后一个字符是不是数字,如果不是数字的话,就去补上一个默认的0,但是还会出现这样的情况0 + (0 - 3) 0 + 3,它把0补到了这里了,这里再去加一个特殊的判断,如果最后一个是 ")" 就不去加上这个默认的0。但是改为之后又出现了这样的情况:0+(0)------------,解决的方法当这个最后一个字符是 "(" 的时候再去增加默认的0。  

声明:

因为作者是一个考研dog,so 没有足够的时间去写这个,只能晚上10回去之后加班写,或者在其他老师课上写,因此间隔时间比较大,而且逻辑比较乱,希望大家多多包涵。 

计划:

1:后期可以去增加一个 按键声音的功能,也即是你点击一个按钮之后,就会产生特定的生硬,当然声音是作者自己那美妙的声音。

2:增加登录操作,把每个人的计算的操作给记录下来,可以查看自己历史计算记录

java代码:

package com.findyou.myapplication;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.math.BigInteger;
import java.util.Objects;
import java.util.Stack;

public class Test_jsq extends AppCompatActivity implements View.OnClickListener {

    private TextView tv_result, show_kh; // 获取文本框的内容 为了进行设置
    // 第一个操作数
    // 第二个操作数
    // 运算符
    private String operator = "";
    // 结果
    private String result = "";
    // 显示的文本内容 刚开始的时候要显示的是 0
    private String showText = "0"; // 3+2

    private Boolean addPoint = true;

    private boolean denominatorIsZero = false; // 分母是否为0

    private final String ISZERO = "分母不可为0!";

    private final String FACTORIALERROR = "小数和分数没有阶乘,阶乘只在自然数中进行";

    private final String OVERFLOW = "溢出";

    private final String NAGATIVE_HAS_NO_FACTORIAL = "负数没有阶乘";

    private final String NAGATIVE_HAS_NO_SQRT = "根号下要大于等于0";

    private final String LN_NEED_GREATER_THAN_ZERO = "ln里面需要大于0";

    // 新增加的 左右括号的显示操作 初始化的括号的数量都显示为 0
    private int leftParenthesis = 0, rightParenthesis = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calculator);

        // 获取tv_result ctrl + alt + f 变为全局变量
        tv_result = findViewById(R.id.tv_result);
        show_kh = findViewById(R.id.show_kh); // 对括号的截取和显示
        Button btn_cancel = findViewById(R.id.btn_cancel);
        btn_cancel.setOnClickListener(this);

        // 给每个按钮设置监听
        findViewById(R.id.btn_cancel).setOnClickListener(this);
        findViewById(R.id.btn_divide) .setOnClickListener(this);//“除法"按钮
        findViewById(R.id.btn_multiply).setOnClickListener(this); // "乘法"按钮
        findViewById(R.id.btn_clear) .setOnClickListener(this);
        findViewById(R.id.btn_seven).setOnClickListener(this); // 数字7
        findViewById(R.id.btn_eight).setOnClickListener(this); // 数字8
        findViewById(R.id.btn_nine).setOnClickListener(this); // 数字9
        findViewById(R.id.btn_plus) .setOnClickListener(this) ;
        findViewById(R.id.btn_four).setOnClickListener(this); // 数字4
        findViewById(R.id.btn_five).setOnClickListener(this); // 数字5
        findViewById(R.id.btn_six) .setOnClickListener(this); // 数字6
        findViewById(R.id.btn_minus).setOnClickListener(this);// "减法"按钮
        findViewById(R.id.btn_one).setOnClickListener(this); // 数字1
        findViewById(R.id.btn_two).setOnClickListener(this); // 数字2
        findViewById(R.id.btn_three).setOnClickListener(this); // 数字3
        findViewById(R.id.btn_reciprocal).setOnClickListener(this);// 求倒数按钮
        findViewById(R.id.btn_zero).setOnClickListener(this); // 数字0
        findViewById(R.id.btn_dot).setOnClickListener(this);// “小数点"按钮
        findViewById(R.id.btn_equal).setOnClickListener(this);// "等号"按钮
        findViewById(R.id.btn_sqrt) .setOnClickListener(this) ;// 开根号按钮
        findViewById(R.id.btn_PI).setOnClickListener(this); // π按钮的监听
        findViewById(R.id.btn_factorial).setOnClickListener(this); // 阶乘按钮的监听
        findViewById(R.id.btn_e).setOnClickListener(this); // e 按钮的监听
        findViewById(R.id.btn_abs).setOnClickListener(this); // 绝对值 按钮的监听

        // 新增加的功能
        findViewById(R.id.btn_left_kh).setOnClickListener(this); // 对左括号 按钮进行监听
        findViewById(R.id.btn_right_kh).setOnClickListener(this); // 对右括号 按钮进行监听
        findViewById(R.id.btn_log).setOnClickListener(this); // 对 log 按钮 进行监听
        findViewById(R.id.btn_ln).setOnClickListener(this); // 对 ln 按钮进行监听
    }

    // 变为公用的
    @Override
    public void onClick(View v) {
        // 测试 是否能正常显示在界面 很好奇 为什么这个 测试的 没有 ban 掉
       // tv_result.setText(((TextView) v).getText().toString());

        String inputText;
        // 如果是开根号的按钮
        if (v.getId() == R.id.btn_sqrt) {
            inputText = "√";
        } else {
            inputText = ((TextView) v).getText().toString();
        }

        int t = v.getId();
        // 点击了清空按钮
        if (t == R.id.btn_clear) {

            // 清空的时候 要去恢复按钮
            illegal(true);
            // 注意二者顺序
            clear();
            // 也要去清空括号
            clearKh();

        } else if(t ==  R.id.btn_cancel) { // 后退按钮
            // 注意 后退 是 不能 去进行 后退 操作符号 的
            showText = Backoff(showText);
            if(Objects.equals(showText, "")) {
                showText = "0"; // 最后一个都被清空了
            }
            // 刷新文本
            refreshText(showText);
        } else if(t == R.id.btn_plus || t == R.id.btn_minus || t == R.id.btn_multiply || t == R.id.btn_divide){ // 点击了 加 减 乘 除
            //  如果操作符的前面是小数点的话 就要把小数点给省略掉 0.1 - 0. + ---> 0.1 - 0 +
            addPoint = true; // 把小数点可以更新了
            operator = inputText;
            char temp = showText.charAt(showText.length() - 1);
            // 每当进行 加减操作的时候 先去看看它的最后一个是不是有效的 不是有效的话 要去主动去增加一个 0  无论是小数点还是普通的加减
            // 增加的 这一个 可能出现了问题了

//            if(!checkIsNum(showText.charAt(showText.length() - 1)) && temp != '(' && temp != ')') {
//                showText = showText + "0";
//            }
            // 这里防止出现这样的情况: (+0)的情况
//            if(checkIskh(temp)) {
//                showText = showText + "0";
//            }

            // 查看当前这个字符串的最后一个 也是操作符的话 就把它给覆盖掉
            if(checkIsOp(temp)) {
                // 就把当前的字符串的最后一个给替换掉
                showText = showText.substring(0, showText.length() - 1) + operator;
                refreshText(showText);
            } else {
                // 这里解决的是 0.-3 这样的问题 解决的方法是把 小数点给去掉
                if(showText.charAt(showText.length() - 1) == '.') {
                    showText = showText.substring(0, showText.length() - 1);
                }
                refreshText(showText + operator);
            }

            //  等号 的操作
        } else if(t == R.id.btn_equal) { // 等号按钮
            // 进行规格化
            String ret = Normalized(js(showText));
            refreshText(ret);

            // 等号的话 也要去恢复小数点的操作
            addPoint = true;
            clearKh();
            // 然后去清空掉
//            showText = "0";
            //1 + 0123.0 √
        } else if(t == R.id.btn_sqrt) { // 开根号
            js3(1); // 1 表示的是开根号的操作
        } else if(t == R.id.btn_reciprocal) { // 求倒数
            js3(2);
        } else if(t == R.id.btn_PI)  { // 点击了 π 的 操作
            js3(4);
        } else if(t == R.id.btn_factorial) { // 点击了阶乘的操作
            js3(3);
        } else if(t == R.id.btn_abs) {
            js3(5); // 点击了绝对值的操作
        } else if(t == R.id.btn_e) { // 点击的是 e 的 操作
            js3(6);
        } else if(t == R.id.btn_ln) { // 点击的是 ln 的操作
            js3(7);
        }
        else if(t == R.id.btn_left_kh) {
            leftParenthesis ++ ;
            // 刷新 界面的括号显示数字 并且把 括号给拼接上去
            // 这里也要特判一下 可能存在 这样的情况 比如: (0)() 要把它变成 (0)x(0) 这样的情况
            char pre = showText.charAt(showText.length() - 1);
            if(pre == ')') {
                showText += 'x';
            }

            // 这里需要去校验一种情况是 1( 要把它变为 1 + (这样的形式
            if(checkIsNum(pre)) {
                showText += "+";
            }
            refreshText(showText + inputText);
        } else if(t == R.id.btn_right_kh) { // 点击了右括号
                // 为了让他们进行匹配 也即是 存在 对应的左括号的时候才进行匹配
                if(rightParenthesis < leftParenthesis) {
                    rightParenthesis ++ ;
                    // 刷新 界面的右括号显示数字 并且把括号给拼接上去
                    // 这里要单独去检验一下 可能是 () 这样的情况是不允许的 要去在左括号的后面去拼接一个 0
                    char pre = showText.charAt(showText.length() - 1);
                    if(pre == '(') {
                        showText += "0";
                     }
                    // 这里也要去防止 (0+)这样的情况
                    if(checkIsOp(pre)) {
                        showText += "0"; // 去给它去补上 0
                    }
                    refreshText(showText + inputText);
                }
        }
        else  {// 点击了 数字 和 小数点
            // 这里要去监控 如果之前点击了小数点 这里的话 就不能再去进行拼接了
            if(inputText.equals(".")) {
                // 这里可能会出现很多的 小数点 例如: 0.000.
                if(!addPoint) { // 表示不可以去添加小数点
                    refreshText(showText); // 保持原来的
                    return ;
                } else {
                    // 这里要去判断一下 小数点的前方是否为操作符 如果是的话 就自动拼接一个 0
                    char pre = showText.charAt(showText.length() - 1);
                    if(checkIsOp(pre) || checkIskh(pre)) {
                        showText = showText + "0";
                    }
                    refreshText(showText + inputText); // 保持原来的
                    addPoint = false;
                    return;
                }
            }
            char pre = showText.charAt(showText.length() - 1);
            // 如果前面不是数字的话 要去自动补上加号
            if(pre == ')') {
                showText += "+";
            }
            refreshText(showText + inputText); // 拼接
        }
    }

    /**
     * 计算的是 开根号 倒数 阶乘 π e
     * @param num 约定好的标志
     *            1:开根号
     *            2:倒数
     *            3:阶乘
     *            4:π
     *            5:绝对值
     *            6:e
     *            7:ln
     */
    private void js3(int num) {
        String snum = getLastNumber(showText);
        String newNumber = "";
        if(num == 1) { // 开根号
            if(Double.parseDouble(snum) < 0) {
                abnormal(NAGATIVE_HAS_NO_SQRT);
                return;
            }
            newNumber = String.valueOf(Math.sqrt(Double.parseDouble(snum)));
        } else if(num == 2) { // 倒数的操作
            // 先去检查分母是不是为0的
            if(Double.parseDouble(snum) - 0.0 == 0) {
                abnormal(ISZERO); // 分母不可为 0
                return ;
            }
            // 开始逻辑上的计算
            newNumber = String.valueOf(1.0 / Double.parseDouble(snum));
        } else if(num == 3) { // 阶乘
            // 注意:小数和分数没有阶乘 阶乘法只在自然数中进行
            if(!addPoint || showText.contains(".")) {
                // 表示当前是增加了小数的 是不能去进行阶乘的运算的
                abnormal(FACTORIALERROR);
                return; // 这个return 是为了防止 其他信息 的覆盖
            } else { // 表示当前是没有小数的 是可以进行阶乘的
                if(Integer.parseInt(snum) > 100) {
                    abnormal(OVERFLOW); // 阶乘太大会导致溢出
                    return ;
                } else if(Integer.parseInt(snum) < 0 ) {
                    abnormal(NAGATIVE_HAS_NO_FACTORIAL); // 负数没有阶乘
                    return;
                }
                newNumber = factorial(Integer.parseInt(snum));
            }
        } else if(num == 4) { //π
            addPoint = false; // 注意 点击了PI 之后也要去限制小数点的
            newNumber = String.valueOf(Math.PI);
        } else if(num == 5) { // 绝对值的操作
            // 感觉这个绝对值 有点鸡肋
            if(Double.parseDouble(snum) < 0 ) {
                newNumber = snum.substring(1); // 把前面的符号给截取掉
            } else {
                // 但是这个新的 还要去规范一下 不能把前置 0 给显示
                newNumber = cancelZero(snum); // 不进行截取
            }

        } else if(num == 6) { // e 2.71828
            newNumber = String.valueOf(Math.E);
        } else if(num == 7) { // ln 的操作
            if(Double.parseDouble(snum) <= 0) {
                abnormal(LN_NEED_GREATER_THAN_ZERO);
                return ;
            }
            newNumber = String.valueOf(Math.log(Double.parseDouble(snum)));
        }
        // 我需要找到最后这个的位置
        // over: 获得这个的num的位置 然后进行替换 把老的替换为新的

        // 我需要去找到 最后一个操作符的位置
        int pos = getLastOperatorPose(showText);

        // 开始进行替代 注意的是 这里的 substring 第二个参数表示的最后的位置 注意是 前闭后开的
        showText = showText.substring(0, pos + 1);

        // 再去拼接新的
        showText = showText + newNumber;

        // 然后再去在界面进行显示出来
        refreshText(showText);

    }

    /**
     * 清空括号 也即是下面这种情况
     * 1: 按下C的时候
     * 2: 等号的时候
     */
    private void clearKh() {
        leftParenthesis = 0;
        rightParenthesis = 0;
        // 清空之后要去刷新 数量
        refreshText(showText);
    }
    /**
     * 对结果进行规格化
     * @param text 传过来 需要规格化的数据
     *             例如: 00001 那么要返回的就是 1
     * @return
     */
    private String cancelZero(String text) { // 取消前置无效0  以及后置无效0
        int j = 0;
        // 要对 test 进行校验一个
        // 有哪些情况呢?
        // 1: 00008
        // 2: 0000.1
        for(int i = 0; i < text.length() - 1; i ++ ) {
            if(text.charAt(i) == '0' && (!checkIsOp(text.charAt(i + 1)) && text.charAt(i + 1) != '.' || text.charAt(i + 1) == ')' || text.charAt(i + 1) == '(')) {
                j = i + 1;
            } else {
                break;
            }
        }
        text = text.substring(j); // 从这里开始截取 并包括当前这个
        return text;
    }

    /**
     * 获取 num 的 阶乘的
     * @param num 想要获取的 阶乘的 num
     * @return
     */
    private String factorial(int num) {
        // 为了解决阶乘太大 用的是 BigInteger
        BigInteger result = BigInteger.ONE; // 初始化为 1
        for (int i = 1; i <= num; i++) {
            result = result.multiply(BigInteger.valueOf(i)); // 逐步相乘
        }
        return String.valueOf(result); // 最后再去转换为 string类型的 给进行输出显示
    }

    /**
     * 根据text 抛出指定的异常
     */
    private void abnormal(String show) {
        // 要去禁用按钮
        illegal(false);
        tv_result.setText(show);; // 并把错误的信息给显示到文本框里面
    }
    /**
     * 后退按钮的操作
     * @param t 出来的逻辑字符串
     * @return 返回的是 后退的字符串
     */
    private String Backoff(String t) {

        for(int i = t.length() - 1; i >= 0; i -- ) {
            if(checkIsNum(t.charAt(i))) {
                // 需要注意的是 如果退的是 小数点的话 要求进行恢复
                if(t.charAt(i) == '.') {
                    // 恢复 可以增加 小数点 的操作
                    addPoint = true;
                }
                // 我就去后退一位
                return t.substring(0, i);

            } else {
                // 否则的话 就直接去回去的
                break;
            }
        }
        return t;
    }

    /**
     * 获得最后一个操作符的位置
     * @param showText 传来的字符串
     * @return 返回的是 最后一个操作符的位置
     * 例如: 1+2 返回的是1
     */
    private int getLastOperatorPose(String showText) {
        int pos = -1;
        if(showText.charAt(0) == '-') {
            return pos;
        }
        for(int i = showText.length() - 1; i >= 0; i -- ) {
            if(checkIsOp(showText.charAt(i)) || checkIskh(showText.charAt(i))) { // 如果检查发现是 操作符的话 就去返回它的下标 是包括它的
                return i;
            }
        }

        // 这个表示的是没有操作符的
        return pos;
    }

    /**
     * 输出结果的规格化
     * @param js
     * @return 返回的是 规格化之后的结果
     */
    private String Normalized(double js) {
        // 是可以去进行规格化的
        if(js - (int)(js) == 0) {
            return String.valueOf((int)(js));
        } else {
            return String.valueOf(js);
        }
    }

    /**
     * 清空 并进行 初始化
     * 新增 对 小数点 的恢复
     */
    private void clear() {
        // 清空的时候 注意把 小数点的功能也给进行恢复
        addPoint = true;
        refreshOperate("");
        refreshText("0"); // 0即表示为不存在 其实也是存在
    }

    // 刷新运算结果
    private void refreshOperate(String new_result) {
        result = new_result;
        operator = "";
    }

    /*
    * 刷新 文本 的操作
    * 再去加上 输出的校验
    * */
    private void refreshText(String text) {
        String khNum = "左括号的数量: " + leftParenthesis + " 右括号的数量: " + rightParenthesis;
        // 这里在刷新的时候 也要把 括号的数量给显示出来
        show_kh.setText(khNum);

        // 在刷新之前 对结果进行规格化一下 去除前置0的 那些没有效的数据 但是要对小数进行特判
        text = cancelZero(text);
        showText = text; // 默认一直在拼接
        if(denominatorIsZero) { // 分母是否为0
            showText = ISZERO;
        }
        tv_result.setText(showText);
        // 对 等号 按钮的监控
        if(leftParenthesis == rightParenthesis) {
            findViewById(R.id.btn_equal).setEnabled(true);
        } else {
            findViewById(R.id.btn_equal).setEnabled(false);
        }
    }


    /**
     * 主要的计算功能
     * @param s 传过来的 字符串 要去计算的字符串 这里面没有等号
     * @return
     */
    private double js(String s) {
        // 第一个的 负数 是比较特殊的 要进行特判
        // 前面直接加上一个 0
        s = "0" + s;
        // 这里需要做一个判断
        // 可能是-3 这样的 但是返回的 也是-3 不要在进行计算下去了 这是一个独特的
//        if(s.charAt(0) == '-') {
//            s = "0" + s;
//        } else if(Objects.equals(operator, "")) {
//            return Double.parseDouble(s);
//        }
        // 用到java里面的桟的算法
        // 存取的是 数字
        Stack<Double> number = new Stack<>();

        // 存取的是 操作符
        Stack<Character> op = new Stack<>();

        String t = "";

       for(int i = 0; i < s.length(); i ++ ) {
           char temp = s.charAt(i);
           // 如果当前这个 temp 是 运算符的话
           if(checkIsOp(temp) || temp == '(' || temp == ')') { // 如果当前这个是 运算符
               // 这样的话 就需要把 字符串给转换为 Double
               // 注意 放进去的前提是不为空的 把他放到 桟里面
               if(!t.isEmpty()) {
                   number.push(Double.valueOf(t));
               }
               t = "";
               // 然后 看看 当前的字符是什么类型的

               if(temp == '+' || temp == '-') {
                   while(!op.isEmpty()) {
                       // 拿到桟顶元素
                       char operator = op.peek();
                       if(operator == '(') { // 左括号的优先级是 最低 的
                           break;
                       }
                       op.pop();

                       // 然后再从 整数桟里面 去拿出来两个数 让其进行计算

                       // TODO: 这两步数 是容易造成 error的 这点需要去着重的去关注
                       double t1 = number.peek();
                       number.pop();

                       double t2 = number.peek();
                       number.pop();

                       // 注意的是 后 操作 前 的
                       double ret = js2(t2, t1, operator);
                       number.push(ret);

                   }
                   // 到这里的时候 就表示 op里面是空的了
                   op.push(temp);
               } else if(temp == 'x' || temp == '÷') {
                   // 当时 乘法或者是 除法的时候 要去校验 它的下面是不是比它低的
                   // 或者可以写成 前提是不为空 然后 op.peek() == 'x' || op.peek() == '➗'
                   while(!op.isEmpty() && op.peek() != '+' && op.peek() != '-' && op.peek() != '(') {
                       // 拿到桟顶元素
                       char operator = op.peek();
                       op.pop();

                       // 然后再从 整数桟里面 去拿出来两个数 让其进行计算
                       // TODO: 这两步数 是容易造成 error的 这点需要去着重的去关注
                       double t1 = number.peek();
                       number.pop();

                       double t2 = number.peek();
                       number.pop();

                       double ret = js2(t2, t1, temp);
                       number.push(ret);
                   }
                   // 到这里的时候 是可以去当进去的
                   op.push(temp);
               } else if(temp == ')') { // 这里对右括号单独进行限制
                   // 只要还没遇到 左括号 就一直去把里面运算符的给弹出来 而且弹出来的时候 也把数字给弹出来两个 然后和这个弹出来的运算符进行计算
                   while(!op.isEmpty()) {
                       char operator = op.peek();
                       op.pop();
                       if(operator == '(') {
                           break; // 就匹配成功了
                       }

                       // 否则的话 就取出来两个数字 然后把这个操作符 让这两个数进行运算的结果 放到存取数的桟里面
                       // TODO: 但是这个的前提是存在的
                       double t1 = number.peek();
                       number.pop();

                       double t2 = number.peek();
                       number.pop();

                       double ret = js2(t2, t1, operator);
                       number.push(ret);
                   }

               } else if(temp == '(') { // 左括号的话 直接 push 进去
                   op.push(temp);
               }

           } else if(checkIsNum(temp)){ // 说明是 数字 或者是小数点
               t = t + temp;
           }
       }
       // Debug 了半天才发现是这里出现了问题 我也是服了
        if(!t.isEmpty()) {
            // 注意在 类型转换的时候 看看是不是为空的 因为空的话 是不能去进行转换的
            number.push(Double.valueOf(t));
        }

       // 开始计算
        while (number.size() > 1) {

            // 这里 没有运算符 也是很致命的
            if(op.isEmpty()) {
                break;
            }

            double t1 = number.peek();
            number.pop();

            double t2 = number.peek();
            number.pop();

            number.push(js2(t2, t1, op.peek()));
            op.pop();
        }
        operator = "";
        return number.peek();

    }

    /**
     * 计算  + - * / 的
     * @param t1
     * @param t2
     * @param temp
     * @return
     */
    private double js2(double t1, double t2, char temp) {

        if(temp == '+') {
            return t1 + t2;
        }

        if(temp == '-') {
            return t1 - t2;
        }

        if(temp == 'x') {
            return t1 * t2;
        }

        if(temp == '÷') {
            // 出现了 分母为0
            if(t2 == 0 ) {
                abnormal(ISZERO); // 分母不可为0 && 限制按钮的点击
            }
            return t1 / t2;
        }
        return 0.0; // 这个是假的
    }


    /**
     * 检查 是不是操作符
     * @param t
     * @return
     */
    private Boolean checkIsOp(Character t) {
        return t == '+' || t == '-' || t == '÷' || t == 'x';
    }

    /**
     * 检查是不是 数字 这里把小数点也认为是数字了
     * @param t
     * @return
     */
    private Boolean checkIsNum(Character t) {
        return (t >= '0' && t <= '9') || t == '.';
    }

    /**
     * 获得字符串 最后 一个 数字
     * @param s
     * @return
     */
    private String getLastNumber(String s) {
        String ret = "";
        if(s.charAt(0) == '-') { // 表示的是负数
            ret = s;
        } else {
            for(int i = s.length() - 1; i >= 0; i -- ) {
                if(checkIsNum(s.charAt(i))) {
                    ret = s.charAt(i) + ret;
                } else {
                    break;
                }
            }
            ret = "0" + ret;
        }

        // 这个去解决的是 1233 + 也即是最后一个不是数字
        if(ret.contains(".")) { // 这个的目的是为了 防止 出现小数点之后 没有出现数字的情况 比如: 123.
            ret = ret + "0";
        }
        return ret;
    }


    /**
     * 去检查这个 t 是不是括号 因为要为括号进行特殊的操作
     * @param t
     * @return
     */
    private boolean checkIskh(char t) {
        return t == '(' || t == ')';
    }

    // 封掉所有的按钮 单独剩下一个 清空的按钮 要去做出适当的提示
    // 表示的是 不合法 把全部的按钮全都给禁用了 除了 C
    private void illegal(boolean value) {
        denominatorIsZero = !value;
        findViewById(R.id.btn_cancel).setEnabled(value);
        findViewById(R.id.btn_divide).setEnabled(value);
        findViewById(R.id.btn_multiply).setEnabled(value);
        findViewById(R.id.btn_clear).setEnabled(true); // 这个是特殊的
        findViewById(R.id.btn_seven).setEnabled(value);
        findViewById(R.id.btn_eight).setEnabled(value);
        findViewById(R.id.btn_nine).setEnabled(value);
        findViewById(R.id.btn_plus).setEnabled(value);
        findViewById(R.id.btn_four).setEnabled(value);
        findViewById(R.id.btn_five).setEnabled(value);
        findViewById(R.id.btn_six).setEnabled(value);
        findViewById(R.id.btn_minus).setEnabled(value);
        findViewById(R.id.btn_one).setEnabled(value);
        findViewById(R.id.btn_two).setEnabled(value);
        findViewById(R.id.btn_three).setEnabled(value);
        findViewById(R.id.btn_reciprocal).setEnabled(value);
        findViewById(R.id.btn_zero).setEnabled(value);
        findViewById(R.id.btn_dot).setEnabled(value);
        findViewById(R.id.btn_equal).setEnabled(value);
        findViewById(R.id.btn_sqrt).setEnabled(value);

        // 新增的 限制按钮
        findViewById(R.id.btn_PI).setEnabled(value);
        findViewById(R.id.btn_factorial).setEnabled(value);
        findViewById(R.id.btn_e).setEnabled(value);
        findViewById(R.id.btn_abs).setEnabled(value);

        // 新增的 限制按钮
        findViewById(R.id.btn_log).setEnabled(value);
        findViewById(R.id.btn_ln).setEnabled(value);
        findViewById(R.id.btn_left_kh).setEnabled(value);
        findViewById(R.id.btn_right_kh).setEnabled(value); // 对右括号 按钮进行监听
    }
}

xml(界面)代码: 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#EEEEEE"
    android:padding="5dp"
    >

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <!--显示简单 计算器 字样-->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/simple_calculator"
                android:gravity="center"
                android:textColor="@color/black"
                android:textSize="20sp"/>

            <TextView
                android:id="@+id/show_kh"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="左括号数量为: 0  右括号数量为: 0"
                android:gravity="center"
                android:textColor="@color/black"
                android:textSize="20sp"/>


            <!-- 计算机 文本的显示-->
            <TextView
                android:id="@+id/tv_result"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:text="0"
                android:textColor="@color/black"
                android:lines="3"
                android:gravity="right|bottom"
                android:textSize="25sp"/>
            
            <GridLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:columnCount="4"
                android:rowCount="7">

                <!--后退一个-->
                <Button
                    android:id="@+id/btn_cancel"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/cancel"
                    android:textColor="@color/black"
                    />

                <!--除法-->
                <Button
                    android:id="@+id/btn_divide"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/divide"
                    android:textColor="@color/black"
                    />

                <!--乘法-->
                <Button
                    android:id="@+id/btn_multiply"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/multiply"
                    android:textColor="@color/black"
                    />

                <!--清零操作-->
                <Button
                    android:id="@+id/btn_clear"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/clear"
                    android:textColor="@color/black"
                    />


                <!--新增的操作-->
                <Button
                    android:id="@+id/btn_PI"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/PI"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_e"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/e"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_abs"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/abs"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_factorial"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/factorial"
                    android:textColor="@color/black"
                    />

                <!--这里又是新增加的 比如 左括号 右括号 -->
                <Button
                    android:id="@+id/btn_log"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/log"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_ln"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="ln"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_left_kh"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/left_kh"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_right_kh"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/right_kh"
                    android:textColor="@color/black"
                    />

                <!--下面是第二行-->

                <Button
                    android:id="@+id/btn_seven"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/seven"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_eight"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/eight"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_nine"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/nine"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_plus"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/plus"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_four"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/four"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_five"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/five"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_six"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/six"
                    android:textColor="@color/black"
                    />


                <Button
                    android:id="@+id/btn_minus"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/minus"
                    android:textColor="@color/black"
                    />


                <Button
                    android:id="@+id/btn_one"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/one"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_two"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/two"
                    android:textColor="@color/black"
                    />

                <Button
                    android:id="@+id/btn_three"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/three"
                    android:textColor="@color/black"
                    />


                <!--这里显示的根号的图片-->
                <Button
                    android:id="@+id/btn_sqrt"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/sqrt"
                    android:textColor="@color/black"
                    />


                <Button
                    android:id="@+id/btn_reciprocal"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/reciprocal"
                    android:textColor="@color/black"
                    />






                <Button
                    android:id="@+id/btn_zero"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/zero"
                    android:textColor="@color/black"
                    />


                <Button
                    android:id="@+id/btn_dot"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/dot"
                    android:textColor="@color/black"
                    />


                <Button
                    android:id="@+id/btn_equal"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:textSize="@dimen/button_font_size"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/equal"
                    android:textColor="@color/black"
                    />






            </GridLayout>


        </LinearLayout>




    </ScrollView>

</LinearLayout>

strings.xml里面的代码:

<resources>
    <string name="app_name">黄淮计算器</string>
    <string name="action_settings">Settings</string>
    <!-- Strings used for fragments for navigation -->
    <string name="first_fragment_label">First Fragment</string>
    <string name="second_fragment_label">Second Fragment</string>
    <string name="next">Next</string>
    <string name="previous">Previous</string>
    <string name="hello_word">hello_word</string>
    <string name="text_for_color">textForColor</string>
    <string name="lorem_ipsum">

    </string>
    <string name="findyou">FindYou</string>
    <string name="this_is_findyou">This is FindYou</string>
    <string name="this_is_activity_main_2">除了奋斗 别无选择</string>


    <!--计算器的定义-->
    <string name="simple_calculator">黄淮计算器</string>
    <string name="cancel">⌫</string>
    <string name="divide">÷</string>
    <string name="multiply">x</string>
    <string name="clear">C</string>
    <string name="seven">7</string>
    <string name="eight">8</string>
    <string name="nine">9</string>
    <string name="plus">+</string>
    <string name="four">4</string>
    <string name="five">5</string>
    <string name="six">6</string>
    <string name="minus">-</string>
    <string name="one">1</string>
    <string name="two">2</string>
    <string name="three">3</string>
    <string name="reciprocal">1/x</string>
    <string name="zero">0</string>
    <string name="dot">.</string>
    <string name="sqrt">√</string>
    <string name="equal">=</string>
    <string name="check_sex">请选择你的性别</string>
    <string name="PI">π</string>
    <string name="e">e</string>
    <string name="abs">|x|</string>
    <string name="factorial">n!</string>
    <string name="log">log</string>
    <string name="left_kh">(</string>
    <string name="right_kh">)</string>

</resources>

如果这对你有帮助的话,记得start一下哦,你的star对我很重要!!!

gitee地址:

FindYou/移动开发

相关文章:

  • el-switch的before-change的使用方法
  • 解决wsl2下CentOS 7 的 yum 仓库无法连接问题
  • Vue舞台剧
  • AWS Lambda:无服务器架构如何重塑云计算,解锁企业敏捷开发与成本革命
  • 目标检测YOLO实战应用案例100讲-基于孤立森林算法的高光谱遥感图像异常目标检测(续)
  • Go语言从零构建SQL数据库引擎 - 开篇
  • 【C++游戏引擎开发】《线性代数》(4):矩阵求逆的LU分解实现(SIMD实现计算加速)
  • 某地81栋危房自动化监测试点项目
  • 深度学习图像分类数据集—五种艺术画风格分类
  • 开源AI大模型赋能的S2B2C商业生态重构研究——基于智能名片系统的体验认知与KOC背书机制
  • 单调自增的数字 斐波那契数列 爬楼梯
  • UML中的用例图和类图
  • npm webpack打包缓存 导致css引用地址未更新
  • C++ 结构体与函数
  • Java基础知识总结(1.8)——Java 注解(持续更新)
  • CSS 父类元素的伪类 选择器
  • FME 中使用 DeepSeek API 与 天地图API
  • 使用perf工具分析Linux系统的性能瓶颈
  • 如何轻松查看安卓手机内存,让手机更流畅
  • (转)子网掩码的作用(1)
  • 市政府统一建设网站的提议/外贸网站推广方法之一
  • 厦门市网站建设app开发/友情链接还有用吗
  • 淘宝做图片的网站/网站制作推广电话
  • 天猫商城官网登录/正规seo关键词排名网络公司
  • 给公司做网站/百度搜不干净的东西
  • 做购物网站数据库分析/免费收录平台