有多种问题在这里:
- 你的方程是不标准C代码。来自Mathematica的
CForm[]
不会将您的代码转换为正确的C语法。也许你可以关注this answer并用SymbolicC
来解决这部分问题
- 你的问题更多的是关于从语言A到语言B的解析。正如在评论中提到的@Olaf:你可能会更好或者使用一个真正的C函数和来自R调用或手动转换它,这取决于你做这个
多久不过,按你的请求(如果我正确理解你想达到的目的)和教育目的;这里的中,我们将用R转换你的“伪C”字符串,并创建一个内联cfunction()
注意一个例子:这是没有意思的意图是优雅或实用的,但总的思路应该希望能帮助你起步
假设下面的公式:
v1 <- "4 * Power(Omega * (-(R * Gamma) + R),(Tau + R))"
摘自原始字符串的所有变量和函数
n1 <- stringi::stri_extract_all_words(v1)[[1]]
创建的“功能重新编写”一个名为向量(如果没有他们,没有NUMERICS一个子集)
newFunc <- c("Power" = "pow")
n2 <- setdiff(n1, names(newFunc))
n3 <- n2[is.na(as.numeric(n2))]
构建替换列表养活gsubfn()
。对于这个例子的目的,我们用新的取代旧的功能和包装asReal()
周围的变量
toreplace <- setNames(
as.list(c(newFunc, paste0("asReal(", n3, ")"))),
c(names(newFunc), n3)
)
v2 <- gsubfn::gsubfn(paste(names(toreplace), collapse = "|"), toreplace, v1)
然后,您可以通过这个新的字符串到cfunction()
R中执行
#install.packages("inline")
library(inline)
foo <- cfunction(
sig = setNames(rep("integer", length(n3)), n3),
body = paste0(
"SEXP result = PROTECT(allocVector(REALSXP, 1));
REAL(result)[0] = ", v2, ";
UNPROTECT(1);
return result;"
)
)
这应该是比使用eval(parse("..."))
与^
或限定Power()
函数更快
Tau = 21; Omega = 22; R = 42; Gamma = 34
Power <- function(x,y) {x^y}
microbenchmark::microbenchmark(
C = foo(Omega, R, Gamma, Tau),
R1 = eval(parse(text="4 * ((Omega * (-(R * Gamma) + R))^(Tau + R))")),
R2 = eval(parse(text="4 * Power(Omega * (-(R * Gamma) + R),(Tau + R))")),
times = 10L
)
#Unit: microseconds
# expr min lq mean median uq max neval
# C 1.233 2.194 5.9555 2.9955 3.302 34.194 10
# R1 190.012 202.781 230.5187 218.1035 243.891 337.209 10
# R2 189.162 191.798 374.5778 207.6875 225.078 1868.746 10
这不是标准的C代码,甚至不是一个表达式。 – Olaf
我提供的第一个代码是Mathematica的CForm []输出的一部分,作为字符串导入到R中。其余全部是R代码。谢谢。 – TK2013
@Olaf是对的。这不是标准的C代码。不要相信'CForm []'将Mathematica表达式转换为C ...看看[this](https://mathematica.stackexchange.com/questions/46844/real-and-or-improved-cform-的表达式) –