直接对double类型的数据进行计算,很容易发生精度丢失问题
使用BigDecimal类计算,可以避免精度丢失
//Double num2 = Double.parseDouble(numStack.pop());
//Double num1 = Double.parseDouble(numStack.pop());
BigDecimal num2 = new BigDecimal(numStack.pop());
BigDecimal num1 = new BigDecimal(numStack.pop());
if(arrays[i].equals("+")){
BigDecimal result = num1.add(num2);
numStack.push(result.toString());
}
else if(arrays[i].equals("-")){
BigDecimal result = num1.subtract(num2);
numStack.push(result.toString());
}
else if(arrays[i].equals("*")){
BigDecimal result = num1.multiply(num2);
numStack.push(result.toString());
}
else if(arrays[i].equals("/")){
BigDecimal result = num1.divide(num2);
numStack.push(result.toString());
}
为了完成多个数据的组合运算,这里使用栈对运算符和运算数进行管理
设计一个存放字符串对象的栈类
public class Stack {
private ArrayList<String> stack = new ArrayList<>();
public boolean isEmpty(){
return stack.size() == 0;
}
public int getSize(){
return stack.size();
}
public String peek(){
if(!isEmpty()) {
return stack.get(stack.size() -1 );
}
else {
return "false";
}
}
public String pop(){
if(!isEmpty()){
String top = stack.get(stack.size() - 1);
stack.remove(stack.size() - 1);
return top;
}
else{
return "false";
}
}
public void push(String o){
stack.add(o);
}
@Override
public String toString(){
return "Stack:" + stack.toString();
}
}
计算类
public class Compute {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String str = input.nextLine();
String[] inOrderArrays = strToArrays(str);
System.out.println(Arrays.toString(inOrderArrays));
String[] postOrderArrays = toPostOrder(inOrderArrays);
System.out.println(Arrays.toString(inOrderArrays));
BigDecimal result = toCompute(postOrderArrays);
System.out.println(result);
}
/*
将字符串分割成操作数和操作符的字符串数组
*/
public static String[] strToArrays(String str){
int strLength = str.length();
int beginIndex = 0; int endIndex = 0;
String[] Arrays = new String[strLength];
int arraysIndex = 0;
for(int i = 0; i < strLength; i++){
if(str.charAt(i)=='*'||str.charAt(i)=='/'||str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='('||str.charAt(i)==')'){
endIndex = i -1 ;
if(beginIndex <= endIndex ){
Arrays[arraysIndex] = str.substring(beginIndex, endIndex+1);
Arrays[arraysIndex + 1] = String.valueOf(str.charAt(i));
arraysIndex += 2;
beginIndex = i + 1;
}
else{
Arrays[arraysIndex] = String.valueOf(str.charAt(i));
arraysIndex += 1;
beginIndex = i + 1;
}
}
}
Arrays[arraysIndex] = str.substring(beginIndex, str.length());
String[] Arrays2 = new String[arraysIndex+1];
for(int i = 0; i < arraysIndex+1; i++) {
Arrays2[i] = Arrays[i];
}
return Arrays2;
}
/*
将中缀表达式转为后缀表达式,返回的是字符串数组
*/
public static String[] toPostOrder(String[] arrays){
/*规则:
*1,运算数直接输出
*2,左括号压入堆栈
*3,右括号 将栈顶的运算符弹出并输出,括号出栈不输出
*4,运算符:
* 若优先级大于栈顶运算符,压入栈
* 若优先级小于或等于栈顶运算符,栈顶运算符弹出并输出,
* 继续和新栈顶比较,直到比栈顶运算符优先级大,将它压入栈
*5,对象处理完毕后,将栈中运算符弹出并输出
*/
Stack operStack = new Stack();//创建了一个操作符的栈
int arraysLength = arrays.length;
String[] arrays2 = new String[arraysLength];//输出后的字符数组
int tempIndex = 0;
//将字符串数组遍历
for(int i = 0; i < arraysLength; i++){
//操作符入栈
if(isOper(arrays[i])){
//栈为空时直接入栈
if(operStack.isEmpty()){
operStack.push(arrays[i]);
}
else{
//操作符为"("时直接入栈
if( arrays[i].equals("(") ){
operStack.push(arrays[i]);
}
//操作符为")"时栈顶出栈并输出,直到遇到"(", "("出栈,")"不入栈
else if( arrays[i].equals(")") ){
while(operStack.peek().equals("(") == false ){
arrays2[tempIndex] = operStack.pop();
tempIndex += 1;
}
operStack.pop();//"("出栈
}
//其他操作符需要比较与栈顶的优先级
else{
//栈顶是"(", 直接入栈
if(operStack.peek().equals("(") ){
operStack.push(arrays[i]);
}
else{
//优先级高,直接入栈
if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))
&& operStack.isEmpty() == false ){
operStack.push(arrays[i]);
}
//优先级低或者相等,栈顶出栈并输出,直到优先级比栈顶高
else{
while(getPriority(arrays[i].charAt(0)) <= getPriority(operStack.peek().charAt(0))
&& operStack.isEmpty() == false){
arrays2[tempIndex] = operStack.pop();
tempIndex += 1;
//若栈顶全部弹出,则直接入栈
if(operStack.isEmpty()) {
operStack.push(arrays[i]);
break;
}
}
if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))){
operStack.push(arrays[i]);
}
}
}
}
}
}
//操作数直接添加到 字符串数组2
else if(isNum(arrays[i])){
arrays2[tempIndex] = arrays[i];
tempIndex += 1;
}
else{
}
}
while(!operStack.isEmpty()){
arrays2[tempIndex] = operStack.pop();
tempIndex += 1;
}
String[] arrays3 = new String[tempIndex];
for(int i = 0; i < tempIndex ;i++){
arrays3[i] = arrays2[i];
}
return arrays3;
}
/*
得到操作符的优先级
*/
public static int getPriority(char c){
if(c == '*' || c == '/'){
return 2;
}
else if (c == '+' || c == '-'){
return 1;
}
else{
return 999;
}
}
/*
由后缀表达式计算得值
*/
public static BigDecimal toCompute(String[] arrays){
/*规则:
*中缀表达式不用比较优先级
*将运算数入栈,每读到一个运算符
*就弹出栈顶的两个运算数,运算完毕后将结果压入栈
*/
Stack numStack = new Stack();//创建了一个操作数的栈
int arraysLength = arrays.length;
//遍历后缀表达式的字符串数组
for(int i = 0; i < arraysLength; i++){
if(isNum(arrays[i])){
numStack.push(arrays[i]);
}
else if(isOper(arrays[i])){
//Double num2 = Double.parseDouble(numStack.pop());
//Double num1 = Double.parseDouble(numStack.pop());
BigDecimal num2 = new BigDecimal(numStack.pop());
BigDecimal num1 = new BigDecimal(numStack.pop());
if(arrays[i].equals("+")){
BigDecimal result = num1.add(num2);
numStack.push(result.toString());
}
else if(arrays[i].equals("-")){
BigDecimal result = num1.subtract(num2);
numStack.push(result.toString());
}
else if(arrays[i].equals("*")){
BigDecimal result = num1.multiply(num2);
numStack.push(result.toString());
}
else if(arrays[i].equals("/")){
BigDecimal result = num1.divide(num2);
numStack.push(result.toString());
}
else{
}
}
else{
}
}
//Double result = Double.parseDouble(numStack.pop());
BigDecimal result = new BigDecimal(numStack.pop());
return result;
}
/*
判断该字符串是否为操作符
*/
public static boolean isOper(String str){
if(str.equals("*")||str.equals("/")||
str.equals("+")||str.equals("-")||
str.equals("(")||str.equals(")")){
return true;
}
else{
return false;
}
}
/*
判断该字符串是否为操作数
*/
public static boolean isNum(String str){
if(str.equals("*")||str.equals("/")||
str.equals("+")||str.equals("-")||
str.equals("(")||str.equals(")")){
return false;
}
else{
return true;
}
}
}