Android简易计算器(四)—— 完整逻辑代码
16lz
2021-01-26
最近在学安卓的相关知识,第一个demo做了一个简易计算器,功能仿手机上自带的计算器,没有加括号,简单的四则运算,支持长表达式运算。此篇贴出本次简易计算器完整逻辑代码。
代码如下:
package com.example.zwkkkk1.caculator1;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.TextView;import java.math.BigDecimal;import java.util.Stack;import java.util.regex.Pattern;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static String TAG = "CACULATOR"; TextView txt_result, txt_edit; boolean isOperateDown = false;//运算符是否已经按过一次,默认没有按过 false boolean isDotDown = false;//. 是否已经按过一次,默认没有按过 false @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txt_edit = (TextView)findViewById(R.id.txt_edit); txt_result = (TextView)findViewById(R.id.txt_result); findViewById(R.id.btn_0).setOnClickListener(this); findViewById(R.id.btn_1).setOnClickListener(this); findViewById(R.id.btn_2).setOnClickListener(this); findViewById(R.id.btn_3).setOnClickListener(this); findViewById(R.id.btn_4).setOnClickListener(this); findViewById(R.id.btn_5).setOnClickListener(this); findViewById(R.id.btn_6).setOnClickListener(this); findViewById(R.id.btn_7).setOnClickListener(this); findViewById(R.id.btn_8).setOnClickListener(this); findViewById(R.id.btn_9).setOnClickListener(this); findViewById(R.id.btn_divide).setOnClickListener(this); findViewById(R.id.btn_multi).setOnClickListener(this); findViewById(R.id.btn_plus).setOnClickListener(this); findViewById(R.id.btn_sub).setOnClickListener(this); findViewById(R.id.btn_equal).setOnClickListener(this); findViewById(R.id.btn_clear).setOnClickListener(this); findViewById(R.id.btn_back).setOnClickListener(this); findViewById(R.id.btn_equal).setOnClickListener(this); findViewById(R.id.btn_dot).setOnClickListener(this); } public void onClick(View v) { switch (v.getId()) { case R.id.btn_0: num_down("0");break; case R.id.btn_1: num_down("1");break; case R.id.btn_2: num_down("2");break; case R.id.btn_3: num_down("3");break; case R.id.btn_4: num_down("4");break; case R.id.btn_5: num_down("5");break; case R.id.btn_6: num_down("6");break; case R.id.btn_7: num_down("7");break; case R.id.btn_8: num_down("8");break; case R.id.btn_9: num_down("9");break; case R.id.btn_plus: operator_down("+");break; case R.id.btn_sub: operator_down("-");break; case R.id.btn_divide: operator_down("÷");break; case R.id.btn_multi: operator_down("×");break; case R.id.btn_clear: isDotDown = false; isOperateDown = false; txt_edit.setText("0"); txt_result.setText(""); break; case R.id.btn_back: { String strEdit = txt_edit.getText().toString(); int length = strEdit.length(); if (Pattern.matches("^=[0-9].*", strEdit)) { txt_edit.setText("0"); txt_result.setText(""); } else { if (length > 0) { String word = strEdit.substring(length - 1, length); if(word.equals(".")) isDotDown = false; if(word.equals("+") || word.equals("-") || word.equals("×") || word.equals("÷")) isOperateDown = false; txt_edit.setText(strEdit.substring(0, length - 1)); } } break; } case R.id.btn_dot: { String strEdit = txt_edit.getText().toString(); if (!isDotDown) { isDotDown = true; if(Pattern.matches("^=[0-9].*", strEdit)) strEdit = "0"; txt_edit.setText(strEdit + "."); } break; } case R.id.btn_equal: equal();break; } } //按下数字函数 private void num_down(String num) { String strEdit = txt_edit.getText().toString(); isOperateDown = false; if (strEdit.equals("0") || Pattern.matches("^=[0-9].*", strEdit)) { txt_edit.setText(num); txt_result.setText(""); } else { txt_edit.setText(strEdit + num); } } // 按下运算符函数 private void operator_down(String operator) { if(!isOperateDown) { String strEdit = txt_edit.getText().toString(); isOperateDown = true; isDotDown = false; if(Pattern.matches("^=[0-9].*", strEdit)) strEdit = strEdit.substring(1, strEdit.length()); txt_edit.setText(strEdit + operator); } } private void equal() { String strEdit = txt_edit.getText().toString(); int length = strEdit.length(); if(!Pattern.matches("^=[0-9].*", strEdit)) { txt_result.setText(strEdit); if(Pattern.matches(".*[\\+\\-\\×\\÷\\.]$", strEdit)) { strEdit = strEdit.substring(0, length - 1); } String postfixExp = getPostfixExp(strEdit); txt_edit.setText("=" + calPostfix(postfixExp)); } } //将中缀表达式转换为后缀表达式 private String getPostfixExp(String str) { String postfix = ""; String numString = ""; //因数字 不止一位需要String存储 Stack numStack = new Stack(); Stack opStack = new Stack(); for(int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if(Character.isDigit(ch) || ch == '.') { //判定ch 是否是数字 或者是 . numString += String.valueOf(ch); //将数字和 .放入numString,等待下一个运算符 } else { //ch为运算符时 if(numString.length() > 0) { numStack.push(numString);//将此运算符前数字压入数字栈 numString = ""; //压入栈后,初始化 numString } opPush(opStack, numStack, ch); } } //最后判定numString是否为空,因为最后一个可能是数字,没有运算符进行判定 if(numString.length() > 0) numStack.push(numString); //检测完后,将运算符栈中转入到数字栈中 while(!opStack.empty()) { numStack.push(opStack.pop()); } //将数字栈打印出来得到后缀表达式 //此处需要将字符串逆序,才得到后缀表达式,但是有小数点的存在,不能直接用 reverse 的逆序函数 //通过两个栈的先进后出特点,得到栈的逆序 while(!numStack.empty()) { opStack.push(numStack.pop()); } while(!opStack.empty()) { postfix = postfix + String.valueOf(opStack.pop()) + " "; } return postfix; } //计算后缀表达式 private String calPostfix(String str) { String result = ""; Stack numStack = new Stack(); for(int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if(ch == ' ') { //运算符时 if(result.length() > 0 && (result.equals("+") || result.equals("-") || result.equals("×") || result.equals("÷"))) { double num = 0; double secondNum = Double.parseDouble(String.valueOf(numStack.pop())); double firstNum = Double.parseDouble(String.valueOf(numStack.pop())); switch (result) { case "+": num = firstNum + secondNum;break; case "-": num = firstNum - secondNum;break; case "×": num = firstNum * secondNum;break; case "÷": num = firstNum / secondNum;break; } numStack.push(num); } else if(result.length() > 0) { numStack.push(result); } result = ""; } else { result += String.valueOf(ch); } } return BigDecimal.valueOf(Double.valueOf(String.valueOf(numStack.pop()))).stripTrailingZeros().toPlainString(); } //获取运算符权重 private int getOpWeight(char ch) { // + - 权重为1 if(ch == '+' || ch == '-') return 1; //× ÷ 权重为2 if(ch == '×' || ch == '÷') return 4; return -1; } //将运算符压入栈 private void opPush(Stack opStack, Stack numStack, char ch) { if(canOpPush(opStack, ch)) { //判定能否将运算符压入栈内 opStack.push(ch); //true则压入栈内 } else { //false(即 待压入运算符优先级 <= 栈顶运算符优先级) //将栈顶运算符取出压入数字栈 numStack.push(String.valueOf(opStack.pop())); //此处需要递归判定,弹出所有优先级 >= 该运算符的栈顶元素 opPush(opStack, numStack, ch); } } //判定运算符能否压入运算符栈 private Boolean canOpPush(Stack opStack, char ch) { //当运算符栈为空时,返回true;或当待压入运算符权重大于栈顶权重,返回true if(opStack.empty() || (getOpWeight(ch) > getOpWeight(String.valueOf(opStack.peek()).charAt(0)))) return true; return false; //其他情况返回false }}
更多相关文章
- Android使用正则表达式验证手机号
- Data Binding(数据绑定)用户指南
- 在Eclipse中对Android应用签名
- 代码设置EditText只输入数字、字母
- DataBinding基础篇
- Android之手机号码格式的正则表达式
- Android百度地图应用开发的前期准备
- Android碎知识点以及正则表达式
- Android(安卓)DataBinding 使用指南