【问题标题】:Replace symbols in string [closed]替换字符串中的符号[关闭]
【发布时间】:2015-09-29 14:12:12
【问题描述】:

如何将 ^ 替换为调用 Math.pow() ? 例如:

str = "10 + 5.2^12"; // -> "10 + Math.pow(5.2, 12)"
str = "2^(12) + 6";  // -> "Math.pow(2, 12) + 6"

【问题讨论】:

  • 您是否尝试过一些代码来实现这一点?如果是这样,请发布相同的内容。
  • 您在寻找表达式评估器吗?
  • 不知道怎么用regxp来形容
  • 字符串是否总是x + y^zx^(y) + z 形式,或者它们可以包含任何形式和长度的算术表达式?
  • 这似乎很容易。我们可以看看你的尝试吗?你肯定读过正则表达式教程,对吧?

标签: java


【解决方案1】:

你可以这样做:

str = str.replaceAll("\\(?(\\d+\\.?\\d*)\\)?\\^\\(?(\\d+\\.?\\d*)\\)?", "Math.pow($1,$2)");

在这种情况下,您正在寻找 2 组数字 (\\d+\\.?\\d*),它们可能是一个浮点值,并且可以在 () \\(?\\)? 的内部。在这两组之间,您需要有 ^ 符号 \\^。如果匹配,则 replaceAll 方法将所有这些模式替换为 Math.pow($1,$2),其中 $1 和 $2 将替换为第一组和第二组数字。

但有一件事,如果你有一个复杂的表达式,它可能会导致错误的结果,连续 2 次乘法,比如 10.22^31.22^5。在这种情况下,这个正则表达式应该要复杂得多。并且可能您应该使用其他算法来解析此类表达式。

【讨论】:

  • 你能解释一下正则表达式吗?
  • 已在编辑答案。添加了简短的解释
  • 谁投了反对票,为什么?
  • 如果你问我,我没有...顺便说一句,我确实赞成
【解决方案2】:

你可以用java中的正则表达式来做到这一点。 使用下面的代码 sn-p 来定义和替换字符串。

private static String replaceMatchPow(String pValue) {
    String regEx = "(\\d*\\.*\\d*)\\^\\(*(\\d*\\.*\\d*)\\)*";
    Pattern pattern = Pattern.compile(regEx);
    Matcher m = pattern.matcher(pValue);
    if (m.find()) {
        String value = "Math.pow(" + m.group(1) + "," + m.group(2) + ")";
        pValue = pValue.replaceAll(regEx, value);
    }
    return pValue;
}

正则表达式如何工作? 这是输入“2^(12) + 6”的示例 第一组 (\d*\.\d)
\d* -> 匹配一个数字 [0-9], * -> 零到无限 \^ -> 按 ^ 符号划分组 (* -> 左括号,* 表示出现次数为零到无限次 第二组 (\d*\.\d)
)* -> 右括号

结果:第一组值为 2,第二组值为 12


/(\d*.*\d*)\^(*(\d*.*\d*))*/
第一个捕获组 (\d*.*\d*)
\d* 匹配一个数字 [0-9]
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
.* 匹配字符 .字面上地
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
\d* 匹配一个数字 [0-9]
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
\^ 匹配字符 ^ 字面意思
(* 匹配字符 ( 字面意思
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
第二个捕获组 (\d*.*\d*)
\d* 匹配一个数字 [0-9]
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
.* 匹配字符 .字面上地
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
\d* 匹配一个数字 [0-9]
量词:*在零次和无限次之间,尽可能多次,按需回馈[贪婪]
)* 匹配字符 ) 字面意思
量词:* 在零次到无限次之间,尽可能多次,按需回馈[贪心]

【讨论】:

  • 你能解释一下正则表达式吗?
  • 例如:第一组 (\\d*\\.*\\d*) \d* -> 匹配数字 [0-9],* -> 零到无限
  • \\^ -> 按 ^ 符号划分组
  • \(* -> 左括号,* 表示出现次数为零到无限制
  • 第二组 (\\d*\\.*\\d*)
【解决方案3】:

对于您的特殊问题,您应该查找插入符号 ^ 在Java regular expressions 中是如何转义的,它应该是\^

注意:

解释 Java 源代码中字符串文字中的反斜杠 根据 Java™ 语言规范的要求,作为 Unicode 转义(第 3.3 节)或其他字符转义(第 3.10.6 节) 因此有必要在字符串文字中加双反斜杠 表示正则表达式以保护它们不被解释 Java 字节码编译器。

所以你最终得到了 "\\^" 作为 Java String

但是,通常您会为算术表达式编写解析器和解释器。

这个主题被称为编译器构造,依赖于有限自动机和形式语言的知识。

可以在 Bjarne Stroustrup 的“The C++ Programming Language, Fourth Edition”的第 10.2 章“A Desk Calculator”中找到一个很好的示例。 (是的,我知道你想用 Java 编写代码,请继续阅读)。 它具有这种形式语法:

program:
  end //end is end-of-input
  expr_list end

expr_list:
  expression print  //pr intis newline or semicolon
  expression print expr_list

expression:
  expression + term
  expression − term
  term

term:
  term / primary
  term ∗ primary
  primary

primary:
  number //number is a floating-point literal
  name //name is an identifier
  name = expression
  −primary
  ( expression )

Stroustrup 向您展示了如何以类似的结构对其进行编码:

double expr(bool get) //add and subtract
{
  double left = term(get);
  for(;;) { //‘‘forever’’
    switch(ts.current().kind) {
    case Kind::plus:
      left += term(true);
      break;
    case Kind::minus:
      left −= term(true);
      break;
    default:
      return left;
    }
  }
}

这段代码体现了这部分语法:

expression:
  expression + term
  expression − term
  term

这种技术称为递归下降,因为语法中的递归将在相应代码中作为递归函数调用来实现。 Java 开发人员也应该可以理解精选的相关 C++ 代码。

一旦您对语法以及如何实现它们有点熟悉, 参见例如Unambiguous grammar for exponentiation operation 如何以满足通常运算符优先级规则的方式处理求幂。

【讨论】:

    猜你喜欢
    • 2020-01-03
    • 1970-01-01
    • 2021-03-25
    • 2014-03-06
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 2013-03-08
    相关资源
    最近更新 更多