简体   繁体   English

使用数学表达式进行 Java 拆分

[英]Java Splitting With Math Expression

I am trying to split a Math Expression.我正在尝试拆分数学表达式。

String number = "100+500";

String[] split = new String[3];

I want to make我要实现

  • split[0] = "100"拆分[0] =“100”
  • split[1] = "+"拆分[1] = "+"
  • split[2] = "500"拆分[2] = "500"

I tried this but I don't know what to write for splitting.我试过这个,但我不知道该写什么来拆分。

split = number.split(????);

You want to split between digits and non-digits without consuming any input... you need look arounds:您想在不消耗任何输入的情况下在数字和非数字之间进行拆分……您需要四处看看:

String[] split = number.split("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)");

What the heck is that train wreck of a regex?正则表达式的火车残骸到底是什么?

It's expressing the initial sentence of this answer:它表达了这个答案的初始句子:

  • (?<=\\d) means the previous character is a digit (?<=\\d)表示前一个字符是数字
  • (?=\\D) means the next character is a non-digit (?=\\D)表示下一个字符是非数字
  • (?<=\\d)(?=\\D) together will match between a digit and a non-digit (?<=\\d)(?=\\D)一起将一个数字和一个非数字之间匹配
  • regexA|regexB means either regexA or regexB is matched, which is used as above points, but non-digit then digit for the visa-versa logic regexA|regexB表示 regexAregexB 匹配,用作上面的点,但非数字然后数字用于反逻辑

An important point is that look arounds are non-consuming , so the split doesn't gobble up any of the input during the split.重要的一点是环顾是非消耗性的,因此拆分过程中不会吞噬任何输入。


Here's some test code:下面是一些测试代码:

String number = "100+500-123/456*789";
String[] split = number.split("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)");
System.out.println(Arrays.toString(split));

Output:输出:

[100, +, 500, -, 123, /, 456, *, 789]

To work with numbers that may have a decimal point, use this regex:要处理可能有小数点的数字,请使用以下正则表达式:

"(?<=[\\d.])(?=[^\\d.])|(?<=[^\\d.])(?=[\\d.])"

which effectively just add .这实际上只是添加. to the characters that are a "number".到作为“数字”的字符。

Off the bat, I don't know any library routine for the split.首先,我不知道拆分的任何库例程。 A custom splitting routine could be like this:自定义拆分例程可能是这样的:

/**
 * Splits the given {@link String} at the operators +, -, * and /
 * 
 * @param string
 *            the {@link String} to be split.
 * @throws NullPointerException
 *             when the given {@link String} is null.
 * @return a {@link List} containing the split string and the operators.
 */
public List<String> split(String string) throws NullPointerException {
    if (string == null)
        throw new NullPointerException("the given string is null!");
    List<String> result = new ArrayList<String>();

    // operators to split upon
    String[] operators = new String[] { "+", "-", "*", "/" };

    int index = 0;
    while (index < string.length()) {
        // find the index of the nearest operator
        int minimum = string.length();
        for (String operator : operators) {
            int i = string.indexOf(operator, index);
            if (i > -1)
                minimum = Math.min(minimum, i);
        }

        // if an operator is found, split the string
        if (minimum < string.length()) {
            result.add(string.substring(index, minimum));
            result.add("" + string.charAt(minimum));
            index = minimum + 1;
        } else {
            result.add(string.substring(index));
            break;
        }
    }

    return result;
}

Some test code:一些测试代码:

System.out.println(split("100+10*6+3"));
System.out.println(split("100+"));

Output:输出:

[100, +, 10, *, 6, +, 3]
[100, +]

You can also use the Pattern/Matcher classes in Java:您还可以在 Java 中使用 Pattern/Matcher 类:

    String expression = "100+34";
    Pattern p = Pattern.compile("(\\d+)|(\\+)");
    Matcher m = p.matcher(expression);
    String[] elems = new String[m.groupCount() +1];
    int i=0;

    while(m.find())
    {
        elems[i++] = m.group();
    }

You can do something simple instead of insane regex;你可以做一些简单的事情而不是疯狂的正则表达式; just pad + with white space:只需用空格填充+

String number = "100+500";
number = number.replace("+", " + ");

Now you can split it at the white space:现在您可以在空白处拆分它:

String[] split = number.split(" ");

Now your indices will be set:现在将设置您的索引:

split[0] = "100";
split[1] = "+";
split[2] = "500";

To check for all arithmetic symbols, you can use the following method if you wish to avoid regex:要检查所有算术符号,如果您希望避免使用正则表达式,可以使用以下方法:

public static String replacing(String s) {
   String[] chars = {"+", "-", "/", "="};

   for (String character : chars) {
      if (s.contains(character)) {
         s = s.replace(character, " " + character + " ");//not exactly elegant, but it works
      }
   }
   return s;
}

//in main method
number = replacing(number);
String[] split = number.split(" ");

You can split your expression string, then in result having pure tokens and categorized tokens.您可以拆分表达式字符串,然后得到纯标记和分类标记。 The mXparser library supports this as well as the calculation process. mXparser库支持此以及计算过程。 Please follow the below example:请按照以下示例操作:

Your very simple example "100+500":你非常简单的例子“100+500”:

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("100+500");
mXparser.consolePrintTokens( e.getCopyOfInitialTokens() );

Result:结果:

[mXparser-v.4.0.0]  --------------------
[mXparser-v.4.0.0] | Expression tokens: |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |    TokenIdx |       Token |        KeyW |     TokenId | TokenTypeId |  TokenLevel |  TokenValue |   LooksLike |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |           0 |         100 |       _num_ |           1 |           0 |           0 |       100.0 |             |
[mXparser-v.4.0.0] |           1 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           2 |         500 |       _num_ |           1 |           0 |           0 |       500.0 |             |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------

More sophisticated example "2*sin(x)+(3/cos(y)-e^(sin(x)+y))+10":更复杂的例子“2*sin(x)+(3/cos(y)-e^(sin(x)+y))+10”:

import org.mariuszgromada.math.mxparser.*;
...
...
Argument x = new Argument("x");
Argument y = new Argument("y");
Expression e = new Expression("2*sin(x)+(3/cos(y)-e^(sin(x)+y))+10", x, y);
mXparser.consolePrintTokens( e.getCopyOfInitialTokens() );

Result:结果:

[mXparser-v.4.0.0]  --------------------
[mXparser-v.4.0.0] | Expression tokens: |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |    TokenIdx |       Token |        KeyW |     TokenId | TokenTypeId |  TokenLevel |  TokenValue |   LooksLike |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |           0 |           2 |       _num_ |           1 |           0 |           0 |         2.0 |             |
[mXparser-v.4.0.0] |           1 |           * |           * |           3 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           2 |         sin |         sin |           1 |           4 |           1 |         NaN |             |
[mXparser-v.4.0.0] |           3 |           ( |           ( |           1 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           4 |           x |           x |           0 |         101 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           5 |           ) |           ) |           2 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           6 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           7 |           ( |           ( |           1 |          20 |           1 |         NaN |             |
[mXparser-v.4.0.0] |           8 |           3 |       _num_ |           1 |           0 |           1 |         3.0 |             |
[mXparser-v.4.0.0] |           9 |           / |           / |           4 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          10 |         cos |         cos |           2 |           4 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          11 |           ( |           ( |           1 |          20 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          12 |           y |           y |           1 |         101 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          13 |           ) |           ) |           2 |          20 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          14 |           - |           - |           2 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          15 |           e |           e |           2 |           9 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          16 |           ^ |           ^ |           5 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          17 |           ( |           ( |           1 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          18 |         sin |         sin |           1 |           4 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          19 |           ( |           ( |           1 |          20 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          20 |           x |           x |           0 |         101 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          21 |           ) |           ) |           2 |          20 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          22 |           + |           + |           1 |           1 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          23 |           y |           y |           1 |         101 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          24 |           ) |           ) |           2 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          25 |           ) |           ) |           2 |          20 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          26 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |          27 |          10 |       _num_ |           1 |           0 |           0 |        10.0 |             |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------

To understand what Token.tokenId and Token.tokenTypeId means you need to refer to the API documentation and parsertokens section.要了解 Token.tokenId 和 Token.tokenTypeId 的含义,您需要参考API 文档和解析器部分。 For instance in Operator class you have例如在 Operator 类中,您有

  1. Operator.TYPE_ID - this corresponds to Token.tokenTypeId if Token is recognized as Operator Operator.TYPE_ID - 如果 Token 被识别为 Operator,则这对应于 Token.tokenTypeId
  2. Operator.OPERATOR_NAME_ID - this corresponds to Token.tokenId if Token is recognized as particular OPERATOR_NAME. Operator.OPERATOR_NAME_ID - 如果 Token 被识别为特定的 OPERATOR_NAME,则这对应于 Token.tokenId。

Please follow mXparser tutorial for better understanding.请遵循mXparser 教程以获得更好的理解。

Best regards此致

Since +,-,* basically all mathematically symbols are special characters so you put a "\\\\" before them inside the split function like this由于 +,-,* 基本上所有数学符号都是特殊字符,因此您可以像这样在 split 函数中在它们之前放置一个“\\\\”

String number = "100+500";
String[] numbers = number.split("\\+");
for (String n:numbers) {
  System.out.println(n);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM