这可能看起来有点过分,但这是我对表达式解析器的实现:
(作为 SSCCE 给出):
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) throws Exception{
System.out.println("Final Output: " + evalutateExpression("(56*3)*(4+3)"));
}
public static double evalutateExpression(String Input){
//This method is extremely sensitive to bad input, try to do some clean up before sending it to the main evaluation body.
Input = Input.replaceAll(" ", ""); //Example of a cleanup
return Double.parseDouble(recursiveEvalutation(Input));
}
private static String recursiveEvalutation(String I){
if(I.contains("(")){
int RIndex = I.indexOf(")");
int LIndex = I.lastIndexOf("(", RIndex);
return recursiveEvalutation(I.substring(0, LIndex) + recursiveEvalutation(I.substring(LIndex + 1, RIndex)) + I.substring(RIndex + 1, I.length()));
}else if(I.contains("^") || I.contains("√")){
int PowerIndex = I.indexOf("^");
int SQRTIndex = I.indexOf("√");
if(PowerIndex == -1){
PowerIndex = Integer.MAX_VALUE;
}
if(SQRTIndex == -1){
SQRTIndex = Integer.MAX_VALUE;
}
if(PowerIndex <= SQRTIndex){
int num2End = findNumberEnd(I.substring(PowerIndex + 1, I.length())) + PowerIndex + 1;
int num1Start = findNumberStart(I.substring(0, PowerIndex));
double Num1 = Double.parseDouble(I.substring(num1Start, PowerIndex));
double Num2 = Double.parseDouble(I.substring(PowerIndex + 1, num2End));
String Eval = new BigDecimal(Math.pow(Num1, Num2)).toPlainString();
return recursiveEvalutation(I.substring(0, num1Start) + Eval + I.substring(num2End, I.length()));
}else{
int num2End = findNumberEnd(I.substring(SQRTIndex + 1, I.length())) + SQRTIndex + 1;
int num1Start = findNumberStart(I.substring(0, SQRTIndex));
double Num1 = Double.parseDouble(I.substring(SQRTIndex + 1, num2End));
String Eval = new BigDecimal(Math.sqrt(Num1)).toPlainString();
return recursiveEvalutation(I.substring(0, num1Start) + Eval + I.substring(num2End, I.length()));
}
}else if(I.contains("*") || I.contains("/")){
int MultiplyIndex = I.indexOf("*");
int DivideIndex = I.indexOf("/");
if(MultiplyIndex == -1){
MultiplyIndex = Integer.MAX_VALUE;
}
if(DivideIndex == -1){
DivideIndex = Integer.MAX_VALUE;
}
if(MultiplyIndex <= DivideIndex){
int num2End = findNumberEnd(I.substring(MultiplyIndex + 1, I.length())) + MultiplyIndex + 1;
int num1Start = findNumberStart(I.substring(0, MultiplyIndex));
double Num1 = Double.parseDouble(I.substring(num1Start, MultiplyIndex));
double Num2 = Double.parseDouble(I.substring(MultiplyIndex + 1, num2End));
String Eval = new BigDecimal(Num1 * Num2).toPlainString();
return recursiveEvalutation(I.substring(0, num1Start) + Eval + I.substring(num2End, I.length()));
}else{
int num2End = findNumberEnd(I.substring(DivideIndex + 1, I.length())) + DivideIndex + 1;
int num1Start = findNumberStart(I.substring(0, DivideIndex));
double Num1 = Double.parseDouble(I.substring(num1Start, DivideIndex));
double Num2 = Double.parseDouble(I.substring(DivideIndex + 1, num2End));
String Eval = new BigDecimal(Num1 / Num2).toPlainString();
return recursiveEvalutation(I.substring(0, num1Start) + Eval + I.substring(num2End, I.length()));
}
}else if(I.contains("+") || I.contains("−")){
int AddIndex = I.indexOf("+");
int MinusIndex = I.indexOf("−");
if(AddIndex == -1){
AddIndex = Integer.MAX_VALUE;
}
if(MinusIndex == -1){
MinusIndex = Integer.MAX_VALUE;
}
if(AddIndex <= MinusIndex){
int num2End = findNumberEnd(I.substring(AddIndex + 1, I.length())) + AddIndex + 1;
int num1Start = findNumberStart(I.substring(0, AddIndex));
double Num1 = Double.parseDouble(I.substring(num1Start, AddIndex));
double Num2 = Double.parseDouble(I.substring(AddIndex + 1, num2End));
String Eval = new BigDecimal(Num1 + Num2).toPlainString();
return recursiveEvalutation(I.substring(0, num1Start) + Eval + I.substring(num2End, I.length()));
}else{
int num2End = findNumberEnd(I.substring(MinusIndex + 1, I.length())) + MinusIndex + 1;
int num1Start = findNumberStart(I.substring(0, MinusIndex));
double Num1 = Double.parseDouble(I.substring(num1Start, MinusIndex));
double Num2 = Double.parseDouble(I.substring(MinusIndex + 1, num2End));
String Eval = new BigDecimal(Num1 - Num2).toPlainString();
return recursiveEvalutation(I.substring(0, num1Start) + Eval + I.substring(num2End, I.length()));
}
}else{
return I;
}
}
private static int findNumberEnd(String I){
char[] expression = I.toCharArray();
for(int x = 0;x < expression.length;x++){
if(!Character.isDigit(expression[x]) && expression[x] != '.' && expression[x] != '-'){
return x;
}
}
return expression.length;
}
private static int findNumberStart(String I){
char[] expression = I.toCharArray();
for(int x = expression.length - 1;x >= 0;x--){
if(!Character.isDigit(expression[x]) && expression[x] != '.' && expression[x] != '-'){
return x + 1;
}
}
return 0;
}
}
遵循递归过程,以遵循运算符优先级连续计算运算符左侧和右侧的表达式。主要评估器是 recursiveEvalutation() 方法。
限制包括:
- 如果输出达到无穷大,则行为未定义。
- 非常密集(创建许多对象,尤其是字符串)
请注意,对于减法,我对运算使用正确的“减号”,对负数使用连字符。
稍微研究一下代码,如果您有任何问题,请随时提出。