在数学表达式中用 C 的 pow 语法替换 ^(幂)符号 [英] Substitute the ^ (power) symbol with C's pow syntax in mathematical expression
问题描述
我有一个数学表达式,例如:
I have a math expression, for example:
((2-x+3)^2+(x-5+7)^10)^0.5
我需要将^
符号替换为C语言的pow
函数.我认为正则表达式是我需要的,但我不知道像专业人士那样的正则表达式.所以我最终得到了这个正则表达式:
I need to replace the ^
symbol to pow
function of C language. I think that regex is what I need, but I don't know a regex like a pro. So I ended up with this regex:
(\([^()]*)*(\s*\([^()]*\)\s*)+([^()]*\))*
我不知道如何改进这一点.你能给我一些建议来解决这个问题吗?
I don't know how to improve this. Can you advice me something to solve that problem?
预期输出:
pow(pow(2-x+3,2)+pow(x-5+7,10),0.5)
推荐答案
这里是一个递归遵循解析树并替换^
的解决方案:
Here is a solution that follows the parse tree recursively and replaces ^
:
#parse the expression
#alternatively you could create it with
#expression(((2-x+3)^2+(x-5+7)^10)^0.5)
e <- parse(text = "((2-x+3)^2+(x-5+7)^10)^0.5")
#a recursive function
fun <- function(e) {
#check if you are at the end of the tree's branch
if (is.name(e) || is.atomic(e)) {
#replace ^
if (e == quote(`^`)) return(quote(pow))
return(e)
}
#follow the tree with recursion
for (i in seq_along(e)) e[[i]] <- fun(e[[i]])
return(e)
}
#deparse to get a character string
deparse(fun(e)[[1]])
#[1] "pow((pow((2 - x + 3), 2) + pow((x - 5 + 7), 10)), 0.5)"
如果 rapply
使用表达式/调用,这会容易得多.
This would be much easier if rapply
worked with expressions/calls.
OP 询问了性能.性能不太可能成为此任务的问题,但正则表达式解决方案并不快.
OP has asked regarding performance. It is very unlikely that performance is an issue for this task, but the regex solution is not faster.
library(microbenchmark)
microbenchmark(regex = {
v <- "((2-x+3)^2+(x-5+7)^10)^0.5"
x <- grepl("(\\(((?:[^()]++|(?1))*)\\))\\^(\\d*\\.?\\d+)", v, perl=TRUE)
while(x) {
v <- sub("(\\(((?:[^()]++|(?1))*)\\))\\^(\\d*\\.?\\d+)", "pow(\\2, \\3)", v, perl=TRUE);
x <- grepl("(\\(((?:[^()]++|(?1))*)\\))\\^(\\d*\\.?\\d+)", v, perl=TRUE)
}
},
BrodieG = {
deparse(f(parse(text = "((2-x+3)^2+(x-5+7)^10)^0.5")[[1]]))
},
Roland = {
deparse(fun(parse(text = "((2-x+3)^2+(x-5+7)^10)^0.5"))[[1]])
})
#Unit: microseconds
# expr min lq mean median uq max neval cld
# regex 321.629 323.934 335.6261 335.329 337.634 384.623 100 c
# BrodieG 238.405 246.087 255.5927 252.105 257.227 355.943 100 b
# Roland 211.518 225.089 231.7061 228.802 235.204 385.904 100 a
我没有包含@digEmAll 提供的解决方案,因为很明显,具有这么多 data.frame 操作的解决方案会相对较慢.
I haven't included the solution provided by @digEmAll, because it seems obvious that a solution with that many data.frame operations will be relatively slow.
编辑 2:
这是一个也处理 sqrt
的版本.
Here is a version that also handles sqrt
.
fun <- function(e) {
#check if you are at the end of the tree's branch
if (is.name(e) || is.atomic(e)) {
#replace ^
if (e == quote(`^`)) return(quote(pow))
return(e)
}
if (e[[1]] == quote(sqrt)) {
#replace sqrt
e[[1]] <- quote(pow)
#add the second argument
e[[3]] <- quote(0.5)
}
#follow the tree with recursion
for (i in seq_along(e)) e[[i]] <- fun(e[[i]])
return(e)
}
e <- parse(text = "sqrt((2-x+3)^2+(x-5+7)^10)")
deparse(fun(e)[[1]])
#[1] "pow(pow((2 - x + 3), 2) + pow((x - 5 + 7), 10), 0.5)"
这篇关于在数学表达式中用 C 的 pow 语法替换 ^(幂)符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!