计算器项目,要求实现加、减、乘、除、求倒数、求平方根等简单运算。
真机调试结果如下图:
布局文件:main_activity.xml
<?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:background=\"#FFFFFF\" android:orientation=\"vertical\" android:padding=\"3dp\"> <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:gravity=\"center\" android:text=\"简单计算器\" android:textColor=\"#000000\" android:textSize=\"20sp\" /> <LinearLayout android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:background=\"#ffffff\" android:orientation=\"vertical\"> <TextView android:id=\"@+id/tv_result\" android:background=\"#4E4B4B\" android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:gravity=\"right|bottom\" android:lines=\"3\" android:maxLines=\"3\" android:scrollbars=\"vertical\" android:text=\"0\" android:textColor=\"#FFFFFF\" android:textSize=\"35sp\" /> </LinearLayout> <GridLayout android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:columnCount=\"4\" > <Button android:id=\"@+id/btn_cancel\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:shadowColor=\"@color/purple_500\" android:text=\"CE\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_divide\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"÷\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_multiply\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"×\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_clear\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"C\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_seven\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"7\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_eight\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"8\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\" /> <Button android:id=\"@+id/btn_nine\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"9\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_plus\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"+\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_four\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"4\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_five\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"5\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_six\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"6\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_minus\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"-\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_one\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"1\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_two\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"2\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_three\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"3\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <ImageButton android:id=\"@+id/ib_sqrt\" android:layout_width=\"90dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:scaleType=\"centerInside\" android:src=\"@drawable/sqrt\" android:gravity=\"center\" android:layout_marginStart=\"4dp\"/> <Button android:id=\"@+id/btn_reciprocal\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"1/x\" android:textColor=\"@color/black\" android:textSize=\"28sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_zero\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"0\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_dot\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\".\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> <Button android:id=\"@+id/btn_equal\" android:layout_width=\"85dp\" android:layout_height=\"70dp\" android:backgroundTint=\"@color/gray\" android:gravity=\"center\" android:text=\"=\" android:textColor=\"@color/black\" android:textSize=\"30sp\" android:layout_marginStart=\"5dp\"/> </GridLayout> </LinearLayout> </ScrollView> </LinearLayout>
活动页面:MainActivity.java
package com.example.calculator; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.example.calculator.cal.CoreAlgorithm; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView tv_result; // 声明一个文本视图对象 private double result =0; // 当前的计算结果 private String showText = \"\"; // 显示的文本内容 private final StringBuilder builder=new StringBuilder(); //存储运算式子的字符串构造器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_result = findViewById(R.id.tv_result); int[] buttonSeq={ R.id.btn_cancel, // “取消”按钮 R.id.btn_divide,// “除法”按钮 R.id.btn_multiply , // “乘法”按钮 R.id.btn_clear , // “清除”按钮 R.id.btn_seven , // 数字7 R.id.btn_eight , // 数字8 R.id.btn_nine , // 数字9 R.id.btn_plus , // “加法”按钮 R.id.btn_four , // 数字4 R.id.btn_five , // 数字5 R.id.btn_six , // 数字6 R.id.btn_minus , // “减法”按钮 R.id.btn_one , // 数字1 R.id.btn_two , // 数字2 R.id.btn_three , // 数字3 R.id.btn_reciprocal , // 求倒数按钮 R.id.btn_zero , // 数字0 R.id.btn_dot , // “小数点”按钮 R.id.btn_equal , // “等号”按钮 R.id.ib_sqrt // “开平方”按钮 }; for(int buttonId:buttonSeq) findViewById(buttonId).setOnClickListener(this); builder.append(0); } //符号分类 //数字 //四则运算符 //小数点 //根号,倒数,等号,直接出结果 //CE C @Override public void onClick(View v) { int id=v.getId(); String inputText=\"\"; // if(result!=0){ //如果结果不为0,则按照结果进行运算 // clear(); // builder.append(result); // } //若不为根号,因为根号按钮无法取值 if(id!=R.id.ib_sqrt) { inputText = ((TextView) v).getText().toString(); //判断是否为数字、小数点以及四则运算符 if (inputText.matches(\"\\\\d|\\\\.\")) { //输入是否为数字或点号 resultCheck(); if(builder.toString().equals(\"0\")){ builder.deleteCharAt(builder.length()-1);} builder.append(inputText); if(verifyExp(builder.toString())){ refreshText(builder.toString()); //表达式正确刷新 }else{ builder.deleteCharAt(builder.length() - 1); //表达式不正确删除最后一位字符 } } else if (inputText.matches(\"\\\\+|-|×|÷\")) { //输入为四则运算符 resultCheck(); builder.append(inputText); if(verifyExp(builder.toString())){ refreshText(builder.toString()); }else{ //更替运算符操作 builder.deleteCharAt(builder.length() - 1); builder.deleteCharAt(builder.length() - 1); builder.append(inputText); refreshText(builder.toString()); } } else { //点击了CE C 1/X = switch (inputText) { case \"CE\": resultCheck(); //有字符才能删除 if (builder.length() > 0) { builder.deleteCharAt(builder.length() - 1); refreshText(builder.toString()); } else { Toast.makeText(this, \"没有数字可删了\", Toast.LENGTH_SHORT).show(); } break; case \"C\": refreshText(\"\"); result=0.0; builder.delete(0, builder.length()); //builder清空 builder.append(0); break; case \"1/x\": resultCheck(); result=1/(CoreAlgorithm.calExp(builder.toString())); refreshText(\"1/(\"+builder.toString()+\")=\\n\"+result); break; case \"=\": resultCheck(); if(result==0.0) { result = CoreAlgorithm.calExp(builder.toString()); // builder.append(\"=\");//容易出错 ,按等号会把这个式子进行运算 refreshText(builder.toString() + \"=\\n\" + result); } break; default: Toast.makeText(this, \"error\", Toast.LENGTH_SHORT).show(); } } }else{ // 点击了开根号,由于算法不支持有运算符在前,目前已经支持 resultCheck(); //经过一次检查结果被清零,结果存于builder中 result = Math.sqrt(CoreAlgorithm.calExp(builder.toString())); refreshText(\"√(\" + builder.toString() + \")=\\n\" + result); } } //检查整个表达式 public boolean verifyExp(String exp){ //验证整个表达式是否合法 String lastNum=\"\"; String[] sp=exp.split(\"\\\\+|-|×|÷\"); //将操作数分割出来 char lastChar=exp.charAt(exp.length()-1); //获得最后一个字符 lastNum=sp[sp.length-1]; //取得最后一位操作数 if(String.valueOf(lastChar).matches(\"\\\\+|-|×|÷\")) //如果当前符号为四则运算符 { lastNum=\"\"; return exp.matches(\".*(\\\\d[+-×÷])|.*(\\\\.[+-×÷])\"); //验证最后的运算符是否符合只有一个原则 }else{ //最后一位为运算数 return lastNum.matches(\"^[-]?\\\\d*\\\\.?\\\\d*\"); //验证最后一位运算数是否合法 } } // 刷新文本显示 private void refreshText(String text) { showText = text; tv_result.setText(showText); } // 清空并初始化 private void clear() { builder.delete(0, builder.length()); showText=\"\"; } //基本每个出结果的按钮都要执行一次这个函数 public void resultCheck(){ //运算结果检查,有结果用结果,结果不为数字进行处理 if(result!=0){ //如果结果不为0,则按照结果进行运算 String res=String.valueOf(result); if(res.matches(\"^[-]?\\\\d*\\\\.?\\\\d*\")){ //若为浮点数字 clear(); builder.append(result); result=0; //结果不清零,检查的时候就会一直重复放入结果 }else{ //若结果为字母,分母为0会返回Infinity,以及负数开方 clear(); builder.append(\"0\"); result=0; } } if(builder.length()==0){ builder.append(0); } } }
核心算法:CoreAlgorithm.java
package com.example.calculator.cal; import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CoreAlgorithm { private static final Stack<Double> st = new Stack<>(); //原始数字栈 private static final Queue<Double> qu = new ArrayDeque<>(); //序列化数字队列, private static final Queue<String> queOp = new ArrayDeque<>(); //符号队列 private static final Queue<String> newQueOp = new ArrayDeque<>(); public static double calExp(String exp) { // String str=\"1+3*2-8/2+6\"; // String str=\"1+3*2/1\"; //本算法似乎不支持符号在前面,目前算法已经改进 //处理运算符在式子最后 if (exp.matches(\".*[\\\\+\\\\-×÷]\")) { exp = exp.substring(0, exp.length() - 1); } String[] sp; //存放分割数组 //运算符在式子最前面 if (exp.matches(\"[\\\\+\\\\-×÷].*\")) { String fistElem=exp.substring(0,1); //截取首个字符 exp=exp.substring(1); //舍去首个字符 //分割字符,提取数字 sp = exp.split(\"\\\\+|-|×|÷\"); if(fistElem.equals(\"-\")){ //首个字符为负号 sp[0]=\"-\"+sp[0]; //添加负号 } }else{ //没有符号在前 sp = exp.split(\"\\\\+|-|×|÷\"); } //之前直接分割字符会导致,数组第一位为空,导致程序无法运行 for (int i = sp.length - 1; i >= 0; i--) { if (sp[i].equals(\".\")) { st.push(0.0); //替换点号 } else { st.push(Double.parseDouble(sp[i])); } } //寻找匹配字符串 Pattern p = Pattern.compile(\"\\\\+|-|×|÷\"); Matcher m = p.matcher(exp); while (m.find()) { queOp.add(m.group()); } // for(int i=sp.length-1;i>=0;i--){ // System.out.println(st.pop()); // } // int size=queNum.size(); // for(int i=0;i<size;i++) // System.out.println(queNum.poll()); //运算降级序列化 while (st.size() > 0) { String currOp; if (queOp.size() > 0) { currOp = queOp.poll(); } else { currOp = \"0\"; } switch (currOp) { case \"×\": st.push(st.pop() * st.pop()); break; case \"÷\": st.push(st.pop() / st.pop()); break; case \"+\": qu.add(st.pop()); newQueOp.add(\"+\"); break; case \"-\": qu.add(st.pop()); newQueOp.add(\"-\"); break; default: qu.add(st.pop()); } } //正常运算 if (qu.size() > 0) { double res = qu.poll(); while (qu.size() > 0) { String op = \"\"; if (newQueOp.size() > 0) { op = newQueOp.poll(); } else { op = \"none\"; } switch (op) { case \"+\": res += qu.poll(); break; case \"-\": res -= qu.poll(); break; default: System.out.println(\"none\"); } } return res; } return 0.0; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。