[英]Split a mathematical expression while handling negative numbers with Java
我正在用Java开发表达式计算器。 我决定先编写一个代码以转换为后缀,然后再编写一个反向波兰表示法计算器。 到目前为止,我的计算器运行良好,可以处理任何表达式,包括运算符+ - * / %
。
但是,我遇到的问题是它使用空格input.split(" ")
拆分了表达式,因此这意味着必须在输入表达式时输入( 4 + ( 2 * ( -2 - 1 ) ) ) * 1.5
input.split(" ")
( 4 + ( 2 * ( -2 - 1 ) ) ) * 1.5
应该可以输入(4+(2*(-2-1)))*1.5
。
经过数小时的修改,我现在知道它不能运行正则表达式,但是它将能够编写一个for循环,一次遍历字符串的两个标记,如果它们都等于一个运算符,则可以假定第二个必须是一个运算符负值。 或者,如果方程式以运算符开头,那么它必须为负值吗? 像这样遍历字符串,直到第二个运算符到达表达式的末尾?
这是我一直试图尝试的一些代码,但是由于我对编程还是很陌生,所以似乎无法使其正常工作。
String expression = "(4+(2*(-2--16)))*-1.5";
ArrayList<String> tokens = new ArrayList<String>();
String orig = null;
String regex = "[-+/*()]+";
String first = Character.toString(expression.charAt(0));
tokens.add(first);
for (int i = 0; i < expression.length(); i++) {
char x = expression.charAt(i);
String a = Character.toString(x);
if (i >= 1){ //Check i is greater than or equal to 1
char y = expression.charAt(i-1);
String b = Character.toString(y);
if(b.matches(regex) && x == '-'){
orig = a;
}else if(orig != null && orig.equals("-")){
System.out.println(orig + a);
tokens.add(orig + a);
orig = null;
}else{
tokens.add(a);
}
}
}
for(String t:tokens){
System.out.print(t+" ");
}
感谢您的帮助,Ciaran。
编辑:
我的问题是我该如何编写一种拆分数学表达式的方法,该方法在拆分时可以区分出作为二进制运算符的“-”和作为一元运算符的“-”? 我是否对字符串进行迭代并比较两个标记的想法正确? – Ciaran Ashton 6分钟前
我要实现的目标是将String expression = (4+(2*(-2-1)))
转换为String[] expression = (, 4, (, 2, *, (, -2, -, 1, ), ), )
使用解析器是更好的解决方案,但是要按照您的要求回答您的问题,您可以使用此正则表达式,它几乎可以完成您想要的操作(不是100%,但是很接近):
(?<=[\(\)\+\-*\/\^A-Za-z])|(?=[\(\)\+\-*\/\^A-Za-z])
因此,您将不得不对其进行转义并像这样使用它:
String input = ...;
String temp[] = input.split("(?<=[\\(\\)\\+\\-*\\/\\^A-Za-z])|(?=[\\(\\)\\+\\-*\\/\\^A-Za-z])");
System.out.println(Arrays.toString(temp));
输入:
7+4-(18/3)/2a^222+1ab
输出:
[7, +, 4, -, (, 18, /, 3, ), /, 2, a, ^, 222, +, 1, a, b]
在这里查看实际操作:
http://rubular.com/r/uHAObPwaln
http://ideone.com/GLFmo4
这可能是解决您的问题的方法,尽管我尚未在各种数据上进行全面测试,但方法是-每当一元运算符出现在expression(全括号表达式)中时,它都将以'('开头,并在其后一个数字。
String expression = "(4+(2*(-2-1)))*1.5";
List<String> tokens = new ArrayList<String>();
String prev = null;
int c = 0;
for (int i = 0; i < expression.length(); i++) {
char x = expression.charAt(i);
String a = Character.toString(x);
if (i >= 1 && expression.charAt(i - 1) == '(' && x == '-') {
prev = a;
} else {
if (prev != null && prev.equals("-")) {
tokens.add(prev + a);
prev = null;
} else {
tokens.add(a);
}
c++;
}
}
这是一个仅使用正则表达式的版本。 它与您的样本输入匹配,但不能处理将一元运算符放在括号前面或嵌套多个一元运算符(例如“ --1”)的情况:
// expression that matches standard Java number formats
// such as 1234, 12.5, and 1.3E-19
String number = "\\d+(?:\\.\\d+(?:(?:E|e)-?\\d+)?)?";
// expression that matches :
// number
// number with unary operator (deemed unary if preceded by (,-,+,/, or *)
// (,),-,+,/, or *
String token = "(" + number + "|(?<=[(-+/*])-" + number + "|[-+/*()])?";
Pattern p = Pattern.compile(token);
Matcher m = p.matcher("(4+(2*(-2-1)))*1.5");
while (m.find()) {
System.out.println(m.group(0));
}
好吧,毕竟在我的指导下,我创建了一个方法,该方法将采用-1+2(4+(2*(-2--1)))*-1.5
并将其拆分为一个数组,例如[-1, +, 2, (, 4, +, (, 2, *, (, -2, -, -1, ), ), ), *, -1.5]
。
该方法的工作方式是使用正则表达式拆分输入String。 使用正则表达式,我可以拆分所有数字和运算符。 尽管这很棒,但它无法处理负值。 使用正则表达式它总是看到-
二元运算符。 我需要将其视为一元运算符,以便它可以理解它是负值。 所以我要做的是将每个运算符与其后的字符串进行比较。 如果这也是一个运算符,我知道第二个是一元运算符。 然后,我还必须输入if语句,以了解第一个值是否为-
以及是否知道那是一元运算符。
到目前为止,这是代码。 我敢肯定,有一种使用解析器进行此操作的简便方法,我只是无法将其包裹住。
import java.util.ArrayList;
import java.util.Arrays;
public class expSplit {
public String[] splitExp(String theexp){
ArrayList<String> tokens = new ArrayList<String>();
//System.out.println(theexp);
String expression = theexp.replaceAll("\\s+", "");
//System.out.println(expression);
String tem[] = expression.split("(?<=[-+*/%(),])(?=.)|(?<=.)(?=[-+*/%(),])");
ArrayList<String> temp = new ArrayList<String>(Arrays.asList(tem));
String orig = null;
String regex = "[-+/%*]+";
String first = temp.get(0);
tokens.add(first);
String secound = temp.get(1);
if(first.equals("-")){
tokens.remove(0);
tokens.add(first+secound);
}
for (int i = 0; i < temp.size(); i++) {
String a = temp.get(i);
if (i >= 1){
String b = temp.get(i-1);
if(b.matches(regex) && a.matches("[-+]+")){
String c = temp.get(i-2);
if(c.matches("[-+]+")){
//System.out.println("MATCH");
break;
}else{
//System.out.println("NO MATCH");
orig = a;
}
}else if(orig != null && orig.equals("-")){
tokens.add(orig + a);
orig = null;
}else{
tokens.add(a);
}
}
}
if(first.equals("+")){
tokens.remove(0);
}
if(first.equals("-")){
tokens.remove(1);
}
String[]tokenArray = new String[tokens.size()];
tokenArray = tokens.toArray(tokenArray);
//System.out.print(tokens);
return tokenArray;
}
}
感谢您的帮助,Ciaran
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.