android封装计算器实现四则运算
前言:
本例子实现了一个简单的计算器的功能,可以实现带括号的四则运算,基本满足日常计算操作,界面布局写的比较简单,布局部分需要的话自己写,只是算法相对比较好,比较简单,拿出来分享一下
实现效果图:
(1)在MainActivity主界面中调用CalcDemo类中的方法,然后把返回的结果赋值给变量,让变量在界面上进行显示,就实现了计算器的效果
//参考网址:https://blog.csdn.net/someone_ikok/article/details/51075839 //本例子只是实现简单的四则运算,布局部分各位可酌情添加 private EditText et; private Button btn; private TextView tv_calc; private CalcDemo calcDemo; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image); et = (EditText)findViewById(R.id.et_calc); btn = (Button)findViewById(R.id.btn_calc); tv_calc = (TextView)findViewById(R.id.tv_calc); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String result = et.getText().toString(); if (!result.equals("")){ double res = calcDemo.exec(result); tv_calc.setText(""+res); } } }); }
(2)计算器的封装类:CalcDemo
public class CalcDemo { /** * * @param exp * 带括号的四则表达式 * @return 运算结果 */ public static double exec(String exp) { // 有括号 // -8*(((-2+4)+3)/((-1-5)*-2)-5) int leftIndex = exp.lastIndexOf('('); // 16 if (leftIndex == -1) { // 没有括号 // System.out.println("calc" + exp); return calc(exp); } else { // 如果有括弧,调用exec // System.out.println("exec" + exp); // 先找最里面的(位置 再找对应的)位置 // (-1-5)*-2)-5) 21 int rightIndex = exp.substring(leftIndex).indexOf(')') + leftIndex; // 去独立的表达式,运算 calc(-1-5) double res = calc(exp.substring(leftIndex + 1, rightIndex)); // 重新组织表达式 exp = exp.substring(0, leftIndex) + res + exp.substring(rightIndex + 1); // -8*(((-2+4)+3)/( -6 *-2)-5) return exec(exp); } // 如果没有括弧 直接调用calc } /** * * @param exp * 不带括号的四则表达式 * @return 运算结果 */ public static double calc(String exp) { // 1 . 获取所有四则运算的数字 List<Double> numbers = sliptNumbers(exp); // 2. 获取所有四则运算的操作符号 List<Character> ops = sliptOps(exp); // 3. 先乘车运算 // 遍历运算符中的*和/ for (int i = 0; i < ops.size(); i++) { // * / // 获取运算符(不移除) char op = ops.get(i); // 如果是 * 或者 /, 从运算符的容器中移除,同是从数字容器中到对应该运算符位置的两个数字(移除数据,后面所有数据往前顺序移动) if (op == '*' || op == '/') { // 从运算符的容器中移除 ops.remove(i);// 移除当前位置 // 从数字容器中获取对应该运算符位置的两个数字(移除) double d1 = numbers.remove(i); double d2 = numbers.remove(i); // 运算 d1 = op == '*' ? d1 * d2 : d1 / d2; // 把运算结果插入到数字容器中的i位置 numbers.add(i, d1);// 插入到i的位置 原来从i位置一直到最后的数据,都要往后瞬移一位 // numbers.set(i, d1);//设置i位置上的数据为d1,其余不变 i--;// 移除后,后面所有运算符往前移动,为了保证下一个运算符不被遗漏,所以i-- }// end if (op == '*' || op == '/') { }// end for (int i = 0 ; i < ops.size(); i++) { // 4. 再加减运算 while (!ops.isEmpty()) { // 每次去运算容器中第一个运算符 char op = ops.remove(0); // 每次从数字容器中两次取第一个数字 double d1 = numbers.remove(0); double d2 = numbers.remove(0); // 计算 d1 = op == '+' ? d1 + d2 : d1 - d2; // 把结果插入到数字容器中的第一个位置 numbers.add(0, d1); } // 5. 返回结果 return numbers.get(0); } /** * 从表达式中分离所有的运算符 * * @param exp */ private static List<Character> sliptOps(String exp) { List<Character> ops = new ArrayList<Character>(); // -8*-2+3/-1-5*-2-5 // 把真实表达式变成下面的表达式 String formaterExp = formaterExp(exp); // @8*@2+3/@1-5*@2-5 StringTokenizer st = new StringTokenizer(formaterExp, "@0123456789."); while (st.hasMoreTokens()) { String opStr = st.nextElement() + "";// 取出分割符号之间的数据 // System.out.println(numStr); // 如果前面是@ 变为负数 ops.add(opStr.charAt(0)); } return ops; } /** * 从表达式中分离所有的数字 * * @param exp * -8*-2+3/-1-5*-2-5 表达式 */ private static List<Double> sliptNumbers(String exp) { List<Double> numbers = new ArrayList<Double>(); // -8*-2+3/-1-5*-2-5 // 把真实表达式变成下面的表达式 String formaterExp = formaterExp(exp); // @8*@2+3/@1-5*@2-5 StringTokenizer st = new StringTokenizer(formaterExp, "+-*/"); while (st.hasMoreTokens()) { String numStr = st.nextElement() + "";// 取出分割符号之间的数据 // System.out.println(numStr); // 如果前面是@ 变为负数 if (numStr.charAt(0) == '@') { numStr = "-" + numStr.substring(1); } // 把数字型的字符串变成数字 numbers.add(Double.parseDouble(numStr)); } return numbers; } private static String formaterExp(String exp) { int index = 0; while (index < exp.length()) { char c = exp.charAt(index); // 判断是否是-符号 // -代表的是负数 第一个,前一字符*/ if (c == '-') { // 第一个, if (index == 0) { exp = "@" + exp.substring(1); } else { // 前一字符* / if (exp.charAt(index - 1) == '*' || exp.charAt(index - 1) == '/') { exp = exp.substring(0, index) + "@" + exp.substring(index + 1); } } } index++; // } return exp; } }