说明
代码逻辑部分是copy的,为了应付课设,就自己弄个布局,本人小白啥也不懂,参考
链接链接地址
运行结果
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp">
<EditText
android:id="@+id/editView"
android:layout_width="360dp"
android:layout_height="80dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:background="@drawable/border"
android:editable="false"
android:gravity="bottom|right"
android:hint="please enter..."
android:textSize="24sp" />
<GridLayout
android:id="@+id/GridLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/editView"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:columnCount="4"
android:orientation="horizontal"
android:rowCount="9">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="(" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text=")" />
<Button
android:layout_width="174dp"
android:layout_columnSpan="2"
android:onClick="delete"
android:text="删除" />
<Button
android:onClick="square"
android:text="x^2" />
<Button
android:onClick="cube"
android:text="x^3" />
<Button
android:id="@+id/button18"
android:layout_width="175dp"
android:layout_height="wrap_content"
android:layout_columnSpan="2"
android:onClick="empty"
android:text="清空" />
<Button
android:onClick="power"
android:text="x^y" />
<Button
android:onClick="factorial"
android:text="x!" />
<Button
android:onClick="squareRoot"
android:text="√" />
<Button
android:onClick="ln"
android:text="ln" />
<Button
android:onClick="log"
android:text="log" />
<Button
android:onClick="eulerNumber"
android:text="e" />
<Button
android:onClick="sin"
android:text="sin" />
<Button
android:onClick="cos"
android:text="cos" />
<Button
android:onClick="tan"
android:text="tan" />
<Button
android:onClick="pi"
android:text="π" />
<Button
android:onClick="reciprocal"
android:text="1/x" />
<Button
android:onClick="percentage"
android:text="%" />
<Button
android:onClick="clickButton"
android:text="+" />
<Button
android:onClick="clickButton"
android:text="1" />
<Button
android:onClick="clickButton"
android:text="2" />
<Button
android:onClick="clickButton"
android:text="3" />
<Button
android:onClick="clickButton"
android:text="-" />
<Button
android:onClick="clickButton"
android:text="4" />
<Button
android:onClick="clickButton"
android:text="5" />
<Button
android:onClick="clickButton"
android:text="6" />
<Button
android:onClick="clickButton"
android:text="*" />
<Button
android:onClick="clickButton"
android:text="7" />
<Button
android:onClick="clickButton"
android:text="8" />
<Button
android:onClick="clickButton"
android:text="9" />
<Button
android:onClick="clickButton"
android:text="/" />
<Button
android:onClick="clickButton"
android:text="." />
<Button
android:onClick="clickButton"
android:text="0" />
<Button
android:onClick="equal"
android:text="=" />
</GridLayout>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:textColor="#FF0000"
android:textSize="20sp" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.calculator;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class MainActivity extends AppCompatActivity {
private EditText editText;
private TextView text; //输入格式错误提示
private Button button;
private StringBuilder str = new StringBuilder(); //参与运算的式子
private int indexYN = 0; //是否出错的标志
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editView);
text = (TextView) findViewById(R.id.textView);
}
//数字及符号按钮
public void clickButton(View view){
button = (Button) view;
editText.append(button.getText());
str.append(button.getText());
}
//清空
public void empty(View view){
editText.setText(null);
str.delete(0,str.length());
}
//删除
public void delete(View view){
String nowText = editText.getText().toString();
if(nowText.length()!=0&&str.length()!=0){
editText.setText(nowText.substring(0,nowText.length()-1));
str.deleteCharAt(str.length()-1);
}
}
//等于
public void equal(View view){
indexYN = 0;
System.out.println("str:\t"+str);
System.out.println("lenth:\t"+str.length());
estimate();
if(indexYN==0){
List<String> zhongZhui = zhuanZhongZhui(str.toString());
System.out.println(zhongZhui);
List<String> houZhui = zhuanHouZhui(zhongZhui);
System.out.println(houZhui);
editText.append("\n"+math(houZhui));
str.delete(0,str.length());
str.append(math(houZhui));
}
}
//倒数
public void reciprocal(View view){
editText.append("1/");
str.append("1/");
}
//阶乘
public void factorial(View view){
editText.append("!");
str.append("!");
}
//平方
public void square(View view){
editText.append("^2");
str.append("^2");
}
//立方
public void cube(View view){
editText.append("^3");
str.append("^3");
}
//幂运算
public void power(View view){
editText.append("^");
str.append("^");
}
//开方
public void squareRoot(View view){
editText.append("√");
str.append("g");
}
//欧拉数e
public void eulerNumber(View view){
editText.append("e");
str.append("e");
}
//百分数
public void percentage(View view){
editText.append("%");
str.append("*0.01");
}
//圆周率
public void pi(View view){
editText.append("π");
str.append("p");
}
//sin
public void sin(View view){
editText.append("sin");
str.append("s");
}
//cos
public void cos(View view){
editText.append("cos");
str.append("c");
}
//tan
public void tan(View view){
editText.append("tan");
str.append("t");
}
//ln
public void ln(View view){
editText.append("ln");
str.append("l");
}
//log
public void log(View view){
editText.append("log");
str.append("o");
}
private List<String> zhuanZhongZhui(String str) {
//把输入的字符串转换成中缀表达式。存入list中
int index = 0;
List<String> list = new ArrayList<>();
do{
char ch = str.charAt(index);
if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){
//是操作符,直接添加至list中
index ++;
list.add(ch+"");
}else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){
index ++;
list.add(ch+"");
} else if("0123456789".indexOf(str.charAt(index)) >= 0){
//是数字,判断多位数的情况
String str1 = "";
while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){
str1 += str.charAt(index);
index ++;
}
list.add(str1);
}
}while (index < str.length());
return list;
}
public List<String> zhuanHouZhui(List<String> list){//中缀表达式转换称后缀表达式
Stack<String> fuZhan = new Stack<>();
List<String> list2 = new ArrayList<>();
if (!list.isEmpty()) {
for (int i = 0; i < list.size(); i++) {
if (isNumber(list.get(i))){
list2.add(list.get(i));
} else if (list.get(i).charAt(0) == '('){
fuZhan.push(list.get(i));
} else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){
if (fuZhan.isEmpty()){
fuZhan.push(list.get(i));
} else {//符栈不为空
if (list.get(i).charAt(0) != ')'){
if (adv(fuZhan.peek()) <= adv(list.get(i))){
//入栈
fuZhan.push(list.get(i));
} else {//出栈
while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){
if(adv(list.get(i)) <= adv(fuZhan.peek())){
list2.add(fuZhan.pop());
}
}
if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){
fuZhan.push(list.get(i));
}
}
} else if (list.get(i).charAt(0) == ')'){
while (fuZhan.peek().charAt(0) != '('){
list2.add(fuZhan.pop());
}
fuZhan.pop();
}
}
}
}
while (!fuZhan.isEmpty()){
list2.add(fuZhan.pop());
}
} else {
editText.setText("");
}
return list2;
}
public static boolean isOperator(String op){//判断是否为操作符
if ("0123456789.ep".indexOf(op.charAt(0)) == -1) {
return true;
} else {
return false;
}
}
public static boolean isNumber(String num){//判断是否为操作数
if ("0123456789ep".indexOf(num.charAt(0)) >= 0) {
return true;
} else {
return false;
}
}
public static int adv(String f){//判断操作符的优先级
int result = 0;
switch(f) {
case "+":
result = 1;
break;
case "-":
result = 1;
break;
case "*":
result = 2;
break;
case "/":
result = 2;
break;
case "^":
result = 3;
break;
case "!":
result = 4;
break;
case "g":
result = 4;
break;
case "l":
result = 4;
break;
case "o":
result = 4;
break;
case "s":
result = 4;
break;
case "c":
result = 4;
break;
case "t":
result = 4;
break;
}
return result;
}
public double math(List<String> list2) {//通过后缀表达式进行计算
Stack<String> stack = new Stack<String>();
for (int i = 0; i < list2.size(); i++) {
if (isNumber(list2.get(i))) {
if (list2.get(i).charAt(0) == 'e'){
stack.push(String.valueOf(Math.E));
} else if (list2.get(i).charAt(0) == 'p'){
stack.push(String.valueOf(Math.PI));
} else {
stack.push(list2.get(i));
}
} else if (isOperator(list2.get(i))){
double res = 0;
if (list2.get(i).equals("+")) {
double num2 = Double.parseDouble(stack.pop());
double num1 = Double.parseDouble(stack.pop());
res = num1 + num2;
} else if (list2.get(i).equals("-")) {
double num2 = Double.parseDouble(stack.pop());
double num1 = Double.parseDouble(stack.pop());
res = num1 - num2;
} else if (list2.get(i).equals("*")) {
double num2 = Double.parseDouble(stack.pop());
double num1 = Double.parseDouble(stack.pop());
res = num1 * num2;
} else if (list2.get(i).equals("/")) {
double num2 = Double.parseDouble(stack.pop());
double num1 = Double.parseDouble(stack.pop());
if (num2 != 0){
res = num1 / num2;
} else {
editText.setText("除数不能为0");
indexYN = 1;
}
} else if (list2.get(i).equals("^")) {
double num2 = Double.parseDouble(stack.pop());
double num1 = Double.parseDouble(stack.pop());
res = Math.pow(num1, num2);
} else if (list2.get(i).equals("!")) {
double num1 = Double.parseDouble(stack.pop());
if (num1 == 0 || num1 == 1){
res = 1;
} else if (num1 == (int)num1 && num1 > 1){
int d = 1;
for (int j = (int)num1; j >0; j--) {
d *= j;
}
res = d;
} else {
editText.setText("阶乘必须为自然数");
indexYN = 1;
}
} else if (list2.get(i).equals("g")) {
double num1 = Double.parseDouble(stack.pop());
res = Math.sqrt(num1);
} else if (list2.get(i).equals("l")) {
double num1 = Double.parseDouble(stack.pop());
if (num1 > 0){
res = Math.log(num1);
} else {
editText.setText("ln的x必须大于0");
indexYN = 1;
}
} else if (list2.get(i).equals("o")) {
double num1 = Double.parseDouble(stack.pop());
if (num1 > 0){
res = Math.log(num1) / Math.log(2);
} else {
editText.setText("log的x必须大于0");
indexYN = 1;
}
} else if (list2.get(i).equals("s")) {
double num1 = Double.parseDouble(stack.pop());
res = Math.sin(num1);
} else if (list2.get(i).equals("c")) {
double num1 = Double.parseDouble(stack.pop());
res = Math.cos(num1);
} else if (list2.get(i).equals("t")) {
double num1 = Double.parseDouble(stack.pop());
if (Math.cos(num1) != 0){
res = Math.tan(num1);
} else {
editText.setText("tan的x不能为+-(π/2 + kπ)");
indexYN = 1;
}
}
stack.push("" + res);
}
}
if (indexYN == 0){
if (!stack.isEmpty()){
return Double.parseDouble(stack.pop());
} else {
return 0;
}
} else {
return -999999;
}
}
public void estimate(){//判断输入是否错误
int i = 0;
if (str.length() == 0){
text.setText("输入为空!");
indexYN = 1;
}
if (str.length() == 1){
//当只有一位字符时,只能是“0123456789ep”中的一个
if ("0123456789ep".indexOf(str.charAt(0)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
}
if (str.length() > 1){
for (i = 0; i < str.length() - 1; i++) {
//1.第一个字符只能为"losctg(0123456789ep"中的一个
if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//2.“+-*/”后面只能是"0123456789losctg(ep"中的一个
if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//3."."后面只能是“0123456789”中的一个
if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//4."!"后面只能是“+-*/^)”中的一个
if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//5."losctg"后面只能是“0123456789(ep”中的一个
if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//6."0"的判断操作
if (str.charAt(0) == '0' && str.charAt(1) == '0'){
text.setText("输入错误!");
indexYN = 1;
}
if (i >= 1 && str.charAt(i) == '0'){
//&& str.charAt(0) == '0' && str.charAt(1) == '0'
int m = i;
int n = i;
int is = 0;
//1.当0的上一个字符不为"0123456789."时,后一位只能是“+-*/.!^)”中的一个
if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//2.如果0的上一位为“.”,则后一位只能是“0123456789+-*/.^)”中的一个
if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
n -= 1;
while (n > 0){
if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){
break;
}
if (str.charAt(n) == '.'){
is++;
}
n--;
}
//3.如果0到上一个运算符之间没有“.”的话,整数位第一个只能是“123456789”,
// 且后一位只能是“0123456789+-*/.!^)”中的一个。
if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//4.如果0到上一个运算符之间有一个“.”的话,则后一位只能是“0123456789+-*/.^)”中的一个
if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
if (is > 1){
text.setText("输入错误!");
indexYN = 1;
}
}
//7."123456789"后面只能是“0123456789+-*/.!^)”中的一个
if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//8."("后面只能是“0123456789locstg()ep”中的一个
if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//9.")"后面只能是“+-*/!^)”中的一个
if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//10.最后一位字符只能是“0123456789!)ep”中的一个
if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
//12.不能有多个“.”
if (i > 2 && str.charAt(i) == '.'){
int n = i - 1;
int is = 0;
while (n > 0){
if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){
break;
}
if (str.charAt(n) == '.'){
is++;
}
n--;
}
if (is > 0){
text.setText("输入错误!");
indexYN = 1;
}
}
//13."ep"后面只能是“+-*/^)”中的一个
if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){
text.setText("输入错误!");
indexYN = 1;
}
}
}
}
}
border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#fff" />
<!-- //设置该控件的背景颜色-->
<!-- //设置边距-->
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
<!-- //控制边界线颜色和笔触大小-->
<stroke
android:width="1dp"
android:color="#CdCdCd" />
<!-- //控制界面颜色渐变(你这个用不到)-->
<gradient
android:startColor="#E9E9E9"
android:endColor="#FFFFFF"
android:type="linear"
android:angle="90"/>
<!-- //控制圆角大小-->
<corners android:radius="2dp" />
<!-- //如果需要制定每个角度大小-->
<corners
android:topRightRadius="2dp"
android:bottomRightRadius="2dp"
android:topLeftRadius="2dp"
android:bottomLeftRadius="2dp"/>
</shape>