结对作业-四则运算升级版

第一阶段目标:重构四则运算-- 能把计算的功能封装起来,通过API 接口调用计算方法。
定义一个计算核心类:把四则运算的计算功能包装在一个模块中 (这个模块可以是一个类 Class,  一个DLL等等)。
 “计算核心”模块和调用类它的其他模块之间是什么关系呢?  
它们要通过一定的API (Application Programming Interface) 来和其他模块交流。
这个API 接口应该怎么设计呢? 可以从下面的最简单的接口开始:
Calc()
这个Calc 函数接受字符串的输入(字符串里就是运算式子,例如 “ 5+3.5“,  “7/8 – 3/8 ”,  “3 + 90 * (-0.3)“  等等),这个模块的返回值是一个字符串,例如,前面几个例子的结果就是 ( ”17.5“, “ 1/2”, “-24“).

package com.az.test.calc;
import java.util.Scanner;
import com.az.test.calc.CreateShiZi;
import com.az.test.calc.NiBoLanShi;
public class Student {
public static void main(String[] args) {
CreateShiZi createShiZi = new CreateShiZi();
NiBoLanShi niBoLanShi = new NiBoLanShi();
String[] fuHao = {"+","-","*","/"};
Scanner input = new Scanner(System.in);
System.out.println("请输入范围内的计算:");
int m = input.nextInt();
System.out.println("请输入要产生的题数:");
int n = input.nextInt();
String[] strArray = new String[n];
System.out.println("
题目
");
createShiZi.create(m, n, fuHao, strArray);
for(int i = 0; i<n; i++) {
String result = niBoLanShi.cal(strArray[i]);
System.out.println("第"+(i+1)+"题:"+strArray[i]);
System.out.print("你的答案:");
String yourAnswer = input.next();
if (yourAnswer.equals(result)) {
System.out.println("True
");
}else {
System.out.println("False");
System.out.println("正确答案:"+result+"
");
}
}
}
}
package com.az.test.calc;
import java.util.List;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Stack;
public class NiBoLanShi {
public static String 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==' ') {
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;

//将中缀表达式转换成后缀表达式
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());
}

//计算后缀表达式的值
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().toString();
}
}
package com.az.test.calc;

public class CreateShiZi {
public void create(int m, int n, String[] fuHao, String[] strArray) {
String str = "";

//随机生成式子
for (int i = 0; i < n; i++) {
str = "";
int[] arr1 = new int[n];
int[] arr2 = new int[n];
arr2[i] = (int)(Math.random()*m+1);
for(int j = 0; j < (int)(Math.random()*10+1); j++) {
int order = (int)(Math.random()*4);
arr1[j] = (int)(Math.random()*m+1);
str = str + arr1[j] + fuHao[order];
}
str = str + arr2[i];
strArray[i] = str;
System.out.println("第"+(i+1)+"题:"+str);
arr1 = null;
arr2 = null;
}
System.out.println("
");
}
}
原文地址:https://www.cnblogs.com/zhjvvvvvv/p/13088167.html