输入一个数n,然后接着输入n行每行含有4个整数的四则运算。
输入中没有括号,若有乘号*或除号/的按顺序先算乘除再算加减,除法保留整数即可。
最后计算每一行的结果,并与24比较,结果是24则输出true,否则输出false。
示例如下:
结题核心是:
1.乘除加减优先级的实现
2.字符串与整数的转换
3.用什么存储输入以及每一次运算后的结果
解决方法:
方法一递归:
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Test {
public static void main(String[] args) throws IOException {
System.out.println("请输入n的值:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println("请输入要计算的四则运算:");
List<String> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
list.add(scanner.next() + "$");
}
list.forEach(s -> System.out.println("24".equals(saveNumber_Symbol(s)) ? true : false));
}
/*分割字符串存储运算符和数字分别到calcuStrList和numberList*/
public static String saveNumber_Symbol(String str) {
char[] strChar = str.toCharArray();
List<String> calcuStrList = new ArrayList<>();//存储运算符号
List<String> numberList = new ArrayList<>();//存储数字
StringBuilder buff = new StringBuilder();
int i = 0;
for (char ch : strChar) {
if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
calcuStrList.add(String.valueOf(ch));
numberList.add(buff.toString());
buff.delete(0, buff.length());
} else if (ch == '$') {//判断是不是最后一个数
numberList.add(buff.toString());
} else {
buff.append(ch);
}
}
return calculationOrder(calcuStrList, numberList);
}
/*控制加减乘除的运算优先级顺序*/
public static String calculationOrder(List<String> calcuStr, List<String> number) {
if (calcuStr.size() > 0) {
int multiply = calcuStr.indexOf("*");
int except = calcuStr.indexOf("/");
//除在前乘在后,或有除无乘,则先算除
if ((-1 != multiply && -1 != except && except < multiply) || (calcuStr.contains("/") && !calcuStr.contains("*"))) {
calcuResult("/", calcuStr, number);
}
//乘在前除在后,或有乘无除,先算乘
if ((-1 != multiply && -1 != except && multiply < except) || (calcuStr.contains("*")&& !calcuStr.contains("/"))) {
calcuResult("*", calcuStr, number);
}
//无乘除只有加减,则从左往右计算
if (calcuStr.size() > 0) {
calcuResult(calcuStr.get(0), calcuStr, number);
}
}
return number.get(0);
}
/*通过symbol找到运算符在calcuStr出现的位置,根据位置在number中找到符号前后的两个数进行计算*/
public static String calcuResult(String symbol, List<String> calcuStr, List<String> number) {
int position = calcuStr.indexOf(symbol);
BigDecimal a = new BigDecimal(number.get(position));
BigDecimal b = new BigDecimal(number.get(position + 1));
String calculateNumber = "";
switch (symbol) {
case "-":
calculateNumber = String.valueOf(a.subtract(b));
break;
case "*":
calculateNumber = String.valueOf(a.multiply(b));
break;
case "/":
calculateNumber = String.valueOf(a.divide(b, 2, RoundingMode.HALF_UP));//除法保留两位小数
break;
default:
calculateNumber = String.valueOf(a.add(b));
}
number.set(position, calculateNumber);//两个数运算完后将计算结果覆盖到第一个数的位置
calcuStr.remove(position);//每用完一个运算符就删除该运算符
number.remove(position + 1);//两个数运算完后删除后面的数
return calculationOrder(calcuStr, number);
}
}
方法二,用栈:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入n的值:");
int n=sc.nextInt();
String[] ss=new String[n];
System.out.println("请输入"+n+"行含有4个整数的四则运算:");
for(int i=0;i<ss.length;i++) {
Scanner sc1 = new Scanner(System.in);
ss[i] = sc1.nextLine();
}
for(String s:ss){
System.out.println(isEqual24(s));
}
}
//判断运算的结果是否等于24
public static boolean isEqual24(String s){
List<String> list=midToAft(s);
if(getResult(list)==24)
return true;
return false;
}
//中缀表达式转后缀表达式
public static List<String> midToAft(String s){
List<String> list=new ArrayList<>();
char[] arr=s.toCharArray();
StringBuffer sb=new StringBuffer();
for(char c:arr){
// 如果是数字或小数点,添加到临时变量中
if (c >= '0' && c <= '9') {
sb.append(c);
}
// 如果是加减乘除,将数字临时变量和运算符依次放入list中
else if (c == '+' || c == '-' || c == '*' || c == '/') {
if (sb.length() > 0) {
list.add(sb.toString());
sb.setLength(0);
}
list.add(c + "");
}
// 如果是空格,跳过
else if (c == ' ') {
continue;
} else {
throw new RuntimeException("非法字符");
}
}
if (sb.length() > 0) {
list.add(sb.toString());
}
List<String> strList = new ArrayList<>();
// 中缀表达式转换为后缀表达式,需要用到栈,转成后缀表达式是为了便于计算
Stack<String> stack = new Stack<>();
// 声明临时变量,存放出栈元素
String tmp;
// 将中缀表达式转换为后缀表达式
for (String str : list) {
// 如果是加减乘除,弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
if (str.equals("*") || str.equals("/")||str.equals("+") || str.equals("-")) {
while (!stack.isEmpty()) {
// 取出栈顶元素
tmp = stack.peek();
// 如果是*和/,因优先级大于等于加减乘除,所以要弹出
if (tmp.equals("*") || tmp.equals("/")) {
stack.pop();
strList.add(tmp);
} else {
break;
}
}
stack.push(str);
}
else {//如果是数字,直接添加到strList中
strList.add(str);
}
}
// 最后依次出栈,放入后缀表达式中
while (!stack.isEmpty()) {
strList.add(stack.pop());
}
return strList;
}
//根据后缀表达式进行四则运算
public static int getResult(List<String> list){
//同样用栈,原则是:遇到数字直接入栈,遇到运算符,就将栈中位于顶部的两个元素弹出并计算,然后将计算结果入栈
Stack<String> stack = new Stack<>();
for(String s:list){
if(s.equals("*")||s.equals("/")||s.equals("-")||s.equals("+")){
int t1=Integer.parseInt(stack.pop());
int t2=Integer.parseInt(stack.pop());
if(s.equals("*")){
stack.push(t1*t2+"");
}else if(s.equals("/")){
stack.push(t2/t1+"");
}else if(s.equals("-")){
stack.push((t2-t1)+"");
}else {
stack.push((t1+t2)+"");
}
}else{
stack.push(s);
}
}
return Integer.parseInt(stack.peek());//栈顶的元素即为计算结果
}
}
方法三:(只能计算一个四则运算):
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Operator {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int nCom = 24;
System.out.print("输入四则运算序列:");
String strIn = sc.next();
while (!strIn.equals("exit")) {
YunSuan ys = new YunSuan(strIn);
System.out.println("运算结果:" + (ys.doYunSuan() == nCom));
strIn = sc.next();
}
System.out.println("程序结束");
}
}
// 执行四则运算类
class YunSuan {
private String strLine; // 输入的运算序列字符串
private List<Integer> digit; // 保存分离出的数值
private List<Character> chara; // 保存分离出的运算符号
private int nOperate; // 当前要进行的运算
private Character sign; // 用于打印运算过程
// 构造函数
public YunSuan(String str) {
this.strLine = str;
nOperate = 0;
Character sign = null;
digit = new ArrayList<Integer>();
chara = new ArrayList<Character>();
}
// 拆分输入的字符串分别到数值列表和运算符列表
public void split() {
String strTemp = "";
Integer n = 0;
for (int i = 0; i < strLine.length(); ++i) {
// 如果是数字型字符添加到临时字符串中
if (Character.isDigit(strLine.charAt(i)))
strTemp += strLine.charAt(i);
else // 如果操作符号添加到运算符号列表中,并转换之前的数字字符为数字并存储
{
Character c = new Character(strLine.charAt(i));
n = Integer.parseInt(strTemp);
digit.add(n);
chara.add(c);
strTemp = "";// 清空准备接受下一个数字
}
}
n = Integer.parseInt(strTemp);
digit.add(n);
}
// 按不同优先级获取运算符号列表中的运算符
// 返回值为该运算符在运算符列表中的索引
// 运算符nOperate:1 +, 2 -, 3 *, 4 /
public int getFuhao() {
boolean bXC = true; // 判断乘法、除法运算是否全部执行完毕
int nSize = chara.size();
if (nSize > 0 && bXC) {
for (int i = 0; i < nSize; i++) {
if (chara.get(i).equals(new Character('*'))) {
sign = chara.get(i); // 用于打印运算过程
chara.remove(i);
nOperate = 3;
return i;
}
if (chara.get(i).equals(new Character('/'))) {
sign = chara.get(i);
chara.remove(i);
nOperate = 4;
return i;
}
}
}
bXC = false;
if (nSize > 0 && !bXC) {
for (int i = 0; i < nSize; i++) {
if (chara.get(i).equals(new Character('+'))) {
sign = chara.get(i);
chara.remove(i);
nOperate = 1;
return i;
}
if (chara.get(i).equals(new Character('-'))) {
sign = chara.get(i);
chara.remove(i);
nOperate = 2;
return i;
}
}
}
return -1;
}
// 执行运算
public int doYunSuan() {
int result = 0; // 保存运算结果
split(); // 分离需要运算的字符串
int nIndex = getFuhao();
int i = 0;// 用于打印运算过程
while ((nIndex != -1) && (nOperate != 0)) {
switch (nOperate) {
case 1:
result = digit.get(nIndex) + digit.get(nIndex + 1);
break;
case 2:
result = digit.get(nIndex) - digit.get(nIndex + 1);
break;
case 3:
result = digit.get(nIndex) * digit.get(nIndex + 1);
break;
case 4:
result = (int) (digit.get(nIndex) / digit.get(nIndex + 1));
break;
default:
break;
}
// 打印运算过程
++i;
System.out.println("第\t" + i + "\t次运算\t" + digit.get(nIndex) + "\t" + sign + "\t" +
digit.get(nIndex + 1) + "\t = \t" + result);
// 删除已经执行过运算的2个数值,并在原位置插入运算结果
digit.set(nIndex, result);
digit.remove(nIndex + 1);
nOperate = 0;
nIndex = getFuhao();
}
if (digit.size() != 1)
System.out.println("error ??????");
return result;
}
}