工程链接
前端界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"><TextViewandroid:id="@+id/hand"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:text="科学计算器"android:textSize="30dp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"><TextViewandroid:id="@+id/edit"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:background="@drawable/shap_rectangle_et"android:maxLines="4"android:minLines="4"android:text=""android:textSize="30dp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center_horizontal"><Buttonandroid:id="@+id/but_CE"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="CE"android:textColor="@color/color_button"android:textSize="30dp" /><Buttonandroid:id="@+id/but_chu"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="/"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_cheng"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="*"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_C"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="C"android:textColor="@color/color_button"android:textSize="50dp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center_horizontal"><Buttonandroid:id="@+id/but_7"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="7"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_8"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="8"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_9"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="9"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_jia"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="+"android:textColor="@color/color_button"android:textSize="50dp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center_horizontal"><Buttonandroid:id="@+id/but_4"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="4"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_5"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="5"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_6"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="6"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_jian"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="-"android:textColor="@color/color_button"android:textSize="50dp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center_horizontal"><Buttonandroid:id="@+id/but_1"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="1"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_2"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="2"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_3"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="3"android:textColor="@color/color_button"android:textSize="50dp" /><ImageButtonandroid:id="@+id/but_eq"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:scaleType="fitCenter"android:src="@drawable/select_button_src_sqrt"></ImageButton></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center_horizontal"><Buttonandroid:id="@+id/but_0"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"android:background="@drawable/select_button"android:text="0"android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_dian"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="."android:textColor="@color/color_button"android:textSize="50dp" /><Buttonandroid:id="@+id/but_dengyu"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/select_button"android:text="="android:textColor="@color/color_button"android:textSize="50dp" /></LinearLayout></LinearLayout>
后端逻辑
import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;public class MainActivity extends AppCompatActivity implements View.OnClickListener {TextView editText;ImageButton but_eq;Button but_cheng;Button but_0;Button but_1;Button but_2;Button but_3;Button but_4;Button but_5;Button but_6;Button but_7;Button but_8;Button but_9;Button but_dian;Button but_dengyu;Button but_chu;Button but_jia;Button but_jian;Button but_C;Button but_CE;String input = "";Boolean clear_flag = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);editText = findViewById(R.id.edit);but_0 = findViewById(R.id.but_0);but_1 = findViewById(R.id.but_1);but_2 = findViewById(R.id.but_2);but_3 = findViewById(R.id.but_3);but_4 = findViewById(R.id.but_4);but_5 = findViewById(R.id.but_5);but_6 = findViewById(R.id.but_6);but_7 = findViewById(R.id.but_7);but_8 = findViewById(R.id.but_8);but_9 = findViewById(R.id.but_9);but_dian = findViewById(R.id.but_dian);but_dengyu = findViewById(R.id.but_dengyu);but_cheng = findViewById(R.id.but_cheng);but_chu = findViewById(R.id.but_chu);but_jia = findViewById(R.id.but_jia);but_jian = findViewById(R.id.but_jian);but_eq = findViewById(R.id.but_eq);but_C = findViewById(R.id.but_C);but_CE = findViewById(R.id.but_CE);but_0.setOnClickListener(this);but_1.setOnClickListener(this);but_2.setOnClickListener(this);but_3.setOnClickListener(this);but_4.setOnClickListener(this);but_5.setOnClickListener(this);but_6.setOnClickListener(this);but_7.setOnClickListener(this);but_8.setOnClickListener(this);but_9.setOnClickListener(this);but_dian.setOnClickListener(this);but_jia.setOnClickListener(this);but_jian.setOnClickListener(this);but_cheng.setOnClickListener(this);but_chu.setOnClickListener(this);but_eq.setOnClickListener(this);but_C.setOnClickListener(this);but_CE.setOnClickListener(this);but_dengyu.setOnClickListener(this);}@Overridepublic void onClick(View v) {try {//获取文本内容input = editText.getText().toString();switch (v.getId()) {case R.id.but_0:case R.id.but_1:case R.id.but_2:case R.id.but_3:case R.id.but_4:case R.id.but_5:case R.id.but_6:case R.id.but_7:case R.id.but_8:case R.id.but_9:case R.id.but_dian:case R.id.but_jia:case R.id.but_jian:case R.id.but_cheng:case R.id.but_chu:if (clear_flag) {clear_flag = false;input = "";editText.setText("");}editText.setText(input + ((Button) v).getText());break;case R.id.but_eq:if (clear_flag) {clear_flag = false;input = "";editText.setText("");}if ((input.length() != 0) && (input.charAt(input.length() - 1) >= '0' && input.charAt(input.length() - 1) <= '9')) {editText.setText(input + "*√");} else editText.setText(input + "√");break;case R.id.but_dengyu:if (input != null || input.length() != 0) {editText.setText(Calculate.getResult(input));clear_flag = true;}break;case R.id.but_C:case R.id.but_CE:editText.setText("");break;default:input = "";editText.setText(input);}} catch (Exception e) {//异常输出editText.setText("语法错误");clear_flag = true;}}
}
数据处理类
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;public class Calculate {//处理字符得出结果public static String getResult(String cal) {return cal(youhua(cal)).toString();}// 计算处理根号 public static String youhua(String str) {String box = new String();int i;for (i = str.length() - 1; i >= 0; i--) {if ('√' == str.charAt(i)) {int a = i + 1;while (a < str.length()) {if ('+' == str.charAt(a) || '-' == str.charAt(a) || '*' == str.charAt(a) || '/' == str.charAt(a)) {box = str.substring(i + 1, a);str = str.replaceAll(str.substring(i, a),String.valueOf(Math.sqrt(cal(str.substring(i + 1, a)).doubleValue())));a = i;break;}a++;}if (a == str.length()) {str = str.substring(0, i) + String.valueOf(Math.sqrt(cal(str.substring(i + 1, a)).doubleValue()));i = str.length() - 1;a = i;}}}return str;}public static BigDecimal cal(String str) {// 对表达式进行预处理,并简单验证是否是正确的表达式// 存放处理后的表达式List<String> list = new ArrayList<>();char[] arr = str.toCharArray();// 存放数字临时变量StringBuffer tmpStr = new StringBuffer();for (char c : arr) {// 如果是数字或小数点,添加到临时变量中if (c >= '0' && c <= '9') {tmpStr.append(c);} else if (c == '.') {if (tmpStr.indexOf(".") > 0) {throw new RuntimeException("非法字符");}tmpStr.append(c);}// 如果是加减乘除或者括号,将数字临时变量和运算符依次放入list中else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') {if (tmpStr.length() > 0) {list.add(tmpStr.toString());tmpStr.setLength(0);}list.add(c + "");}// 如果是空格,跳过else if (c == ' '||c=='\n') {continue;} else {throw new RuntimeException("非法字符");}}if (tmpStr.length() > 0) {list.add(tmpStr.toString());}// 初始化后缀表达式List<String> strList = new ArrayList<>();// 运算过程中,使用了两次栈结构,第一次是将中缀表达式转换为后缀表达式,第二次是计算后缀表达式的值Stack<String> stack = new Stack<>();// 声明临时变量,存放出栈元素String tmp;// 1. 将中缀表达式转换为后缀表达式for (String s : list) {// 如果是左括号直接入栈if (s.equals("(")) {stack.push(s);}// 如果是右括号,执行出栈操作,依次添加到后缀表达式中,直到出栈元素为左括号,左括号和右括号都不添加到后缀表达式中else if (s.equals(")")) {while (!(tmp = stack.pop()).equals("(")) {strList.add(tmp);}}// 如果是加减乘除,弹出所有优先级大于或者等于该运算符的栈顶元素(栈中肯定没有右括号,认为左括号的优先级最低),然后将该运算符入栈else if (s.equals("*") || s.equals("/")) {while (!stack.isEmpty()) {// 取出栈顶元素tmp = stack.peek();if (tmp.equals("*") || tmp.equals("/")) {stack.pop();strList.add(tmp);} else {break;}}stack.push(s);} else if (s.equals("+") || s.equals("-")) {while (!stack.isEmpty()) {// 取出栈顶元素tmp = stack.peek();if (!tmp.equals("(")) {stack.pop();strList.add(tmp);} else {break;}}stack.push(s);}// 如果是数字,直接添加到后缀表达式中else {strList.add(s);}}// 最后依次出栈,放入后缀表达式中while (!stack.isEmpty()) {strList.add(stack.pop());}// 2.计算后缀表达式的值Stack<BigDecimal> newStack = new Stack<>();for (String s : strList) {// 若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,// 运算后的结果再进栈,直到后缀表达式遍历完毕if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {BigDecimal b1 = newStack.pop();BigDecimal b2 = newStack.pop();switch (s) {case "+":newStack.push(b2.add(b1));break;case "-":newStack.push(b2.subtract(b1));break;case "*":newStack.push(b2.multiply(b1));break;case "/":newStack.push(b2.divide(b1, 9, BigDecimal.ROUND_HALF_UP));break;}}// 如果是数字,入栈else {newStack.push(new BigDecimal(s));}}// 最后,栈中仅有一个元素,就是计算结果return newStack.peek();}}