【问题标题】:Java Splitting With Math Expression使用数学表达式进行 Java 拆分
【发布时间】:2015-03-04 16:16:19
【问题描述】:

我正在尝试拆分数学表达式。

String number = "100+500";

String[] split = new String[3];

我想做

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

我试过这个,但我不知道写什么来分裂。

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

【问题讨论】:

  • 为什么要拆分呢?编写解析器或评估表达式?在这两种情况下,拆分可能都不是正确的工具。
  • @assylias 我正在为大整数制作一个 GUI 计算器。拆分后,我会检查使用了哪个运算符,然后我会评估它。
  • Split 使用正则表达式,所以这可能很有趣:stackoverflow.com/questions/24463048/…
  • 哎呀,我误读了这个问题。拆分可能不是这项工作的最佳工具,因为它会消耗要拆分的角色。
  • @Makoto 是的,我试过了,但我找不到操作员。我将只使用 +,- 和 * 运算符,所以我所要做的就是拆分这 3 个。

标签: java math


【解决方案1】:

您想在不消耗任何输入的情况下在数字和非数字之间进行拆分...您需要环顾四周:

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

正则表达式的火车残骸到底是什么?

表达了这个答案的首句:

  • (?&lt;=\d) 表示前一个字符是数字
  • (?=\D) 表示下一个字符是非数字
  • (?&lt;=\d)(?=\D) 一起将匹配 一个数字和一个非数字
  • regexA|regexB 表示匹配正则表达式A 正则表达式B,如上所用,但反之亦然,非数字则为数字

重要的一点是,环顾四周是非消耗性的,因此在拆分过程中拆分不会吞噬任何输入。


这是一些测试代码:

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

输出:

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

要处理可能有小数点的数字,请使用以下正则表达式:

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

实际上只是将. 添加到“数字”字符中。

【讨论】:

  • 它工作了......但是怎么样? "(?
  • @Dosher:查看docs.oracle.com/javase/tutorial/essential/regex。预定义的字符类将解释 \d 和 \D 的作用。其他方法应该解释正则表达式的其余部分。
  • @Bohemian 这对我帮助很大,现在我明白了。非常感谢!
  • @realNameDoesn'tExist 查看补充回答
  • @Narshe 添加这个:(?=[()])|(?&lt;=[()]),即"(?&lt;=[\\d.])(?=[^\\d.])|(?&lt;=[^\\d.])(?=[\\d.])|(?=[()])|(?&lt;=[()])" 在括号前后分开。
【解决方案2】:

顺便说一句,我不知道任何用于拆分的库例程。自定义拆分例程可能是这样的:

/**
 * 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;
}

一些测试代码:

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

输出:

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

【讨论】:

    【解决方案3】:

    您还可以在 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();
        }
    

    【讨论】:

      【解决方案4】:

      你可以做一些简单的事情而不是疯狂的正则表达式;只需用空格填充+

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

      现在你可以在空白处分割它:

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

      现在您的索引将被设置:

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

      要检查所有算术符号,如果您希望避免使用正则表达式,可以使用以下方法:

      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(" ");
      

      【讨论】:

      • 这对我来说是一个很好的方法,但我还需要拆分 - 和 。将 number = number.replace("+", "+" || "-", "-" || "", "*");工作? --编辑:好的,它没有用。
      • 不幸的是,您必须为您希望填充的每个字符添加一个.replace() 才能使此技术起作用。一种解决方法是创建一个方法来检查所有需要拆分的区域,并不断更新字符串,然后返回它。您的字符,例如 *- 可以放在一个数组中进行迭代。好处是你只需要写一次replace(),所以你的代码看起来更优雅。不过性能还是一样的。
      【解决方案5】:

      您可以拆分您的表达式字符串,然后得到具有纯标记和分类标记的结果。 mXparser 库支持这一点以及计算过程。请按照以下示例:

      你非常简单的例子“100+500”:

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

      结果:

      [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]  ---------------------------------------------------------------------------------------------------------------
      

      更复杂的例子“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() );
      

      结果:

      [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]  ---------------------------------------------------------------------------------------------------------------
      

      要了解 Token.tokenId 和 Token.tokenTypeId 的含义,您需要参考 API documentation 和 parsertokens 部分。例如在 Operator 类中你有

      1. Operator.TYPE_ID - 如果 Token 被识别为 Operator,则这对应于 Token.tokenTypeId
      2. Operator.OPERATOR_NAME_ID - 如果 Token 被识别为特定的 OPERATOR_NAME,则这对应于 Token.tokenId。

      请关注mXparser tutorial以便更好地理解。

      最好的问候

      【讨论】:

        【解决方案6】:

        由于 +,-,* 基本上所有数学符号都是特殊字符,因此您可以像这样在拆分函数中在它们之前放置一个“\\”

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-02
          • 2019-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-27
          相关资源
          最近更新 更多