簡體   English   中英

使用Java處理負數時拆分數學表達式

[英]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, ), ), )

這對於適當的解析器生成器來說是一項工作。 Java世界中最著名的是JavaCCAntlr 我喜歡將JFlex與JavaCC搭配使用。

它們的好處是,您可以根據上下文為令牌賦予不同的含義。 因此,減號在一個地方可能意味着一件事,而在另一地方可能意味着另一件事。

使用解析器是更好的解決方案,但是要按照您的要求回答您的問題,您可以使用此正則表達式,它幾乎可以完成您想要的操作(不是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM