在建立分数多项式函数时避免使用eval(parse())

编程入门 行业动态 更新时间:2024-10-24 14:15:49
本文介绍了在建立分数多项式函数时避免使用eval(parse())的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我的目标是在R中编写一个函数,该函数接受分数多项式(FP)并返回向量化函数,该函数针对给定的输入数字评估指定的FP. FP定义有两个重要规则:

My goal is to write a function in R that accepts coefficients for a fractional polynomial (FP) and returns a vectorized function which evaluates the specified FP for given input numbers. The FP definition has two important rules:

  • x ^ 0定义为log(x)
  • 幂可以具有多个系数,其中幂p的第二个系数将加法项(x ^ p * log(x))加一个log(x)因子,第三个系数加一个log(x)^因子2(x ^ p * log(x)^ 2),依此类推

我下面的当前解决方案将FP函数构建为字符串,解析该字符串并返回一个计算表达式的函数.我的问题是,是否有更好/更快的方法来避免eval(parse())-可能使用某些substitute()魔术.

My current solution below builds the FP-function as a string, parses the string and returns a function which evaluates the expression. My question is if there is a better/faster way that avoids eval(parse()) - possibly using some substitute() magic.

函数必须处理,该函数具有预先未知的每幂系数数,但在调用时指定. FP的最终评估经常要被调用.

The function must deal with having the number of coefficients per power not known in advance, but specified when being called. The final FP evaluation needs to be fast as it is called very often.

很好,不应该局限于标准幂-2,-1,-0.5、0、0.5、1、2、3.理想情况下,所需的函数将同时执行两个步骤:接受FP系数以及数字向量,并在保持快速的同时返回输入的FP值.

It would be nice not to be limited to the standard powers -2, -1, -0.5, 0, 0.5, 1, 2, 3. Ideally, the desired function would do two steps at once: accept FP-coefficients as well as a vector of numbers and return the FP-values for the input while still being fast.

getFP <- function(p_2, p_1, p_0.5, p0, p0.5, p1, p2, p3, ...) { p <- as.list(match.call(expand.dots=TRUE)[-1]) # all args names(p) <- sub("^p", "", names(p)) # strip "p" from arg names names(p) <- sub("_", "-", names(p)) # replace _ by - in arg names ## for one power and the i-th coefficient: build string getCoefStr <- function(i, pow, coefs) { powBT <- ifelse(as.numeric(pow), paste0("x^(", pow, ")"), "log(x)") logFac <- ifelse(i-1, paste0("*log(x)^", i-1), "") paste0("(", coefs[i], ")*", powBT, logFac) } onePwrStr <- function(pow, p) { # for one power: build string for all coefs coefs <- eval(p[[pow]]) pwrStr <- sapply(seq(along=coefs), getCoefStr, pow, coefs) paste(pwrStr, collapse=" + ") } allPwrs <- sapply(names(p), onePwrStr, p) # for each power: build string fpExpr <- parse(text=paste(allPwrs, collapse=" + ")) function(x) { eval(fpExpr) } }

例如-1.5*x^(-1) - 14*log(x) - 13*x^(0.5) + 6*x^0.5*log(x) + 1*x^3,它具有指定的幂(-1、0、0.5、0.5、3),系数为(-1.5,-14,-13、6、1).

An example would be -1.5*x^(-1) - 14*log(x) - 13*x^(0.5) + 6*x^0.5*log(x) + 1*x^3 which has specified powers (-1, 0, 0.5, 0.5, 3) with coefficients (-1.5, -14, -13, 6, 1).

> fp <- getFP(p_1=-1.5, p0=-14, p0.5=c(-13, 6), p3=1) > fp(1:3) [1] -13.50000000 -14.95728798 0.01988127

推荐答案

首先,我们创建一个将在序列中生成单个术语的函数

First we create a function that will generate a single term in the sequence

one <- function(p, c = 1, repeated = 1) { if (p == 0) { lhs <- substitute(c * log(x), list(c = c)) } else { lhs <- substitute(c * x ^ p, list(c = c, p = p)) } if (repeated == 1) return(lhs) substitute(lhs * log(x) ^ pow, list(lhs = lhs, pow = repeated - 1)) } one(0) # 1 * log(x) one(2) # 1 * x^2 one(2, 2) # 2 * x^2 one(2, r = 2) # 1 * x ^ 2 * log(x)^1 one(2, r = 3) # 1 * x ^ 2 * log(x)^2

此处的关键工具是substitute(),此处.

接下来,我们编写一个将两个项加在一起的函数.再次使用替代:

Next we write a function that will add together two terms. Again this uses substitute:

add_expr_1 <- function(x, y) { substitute(x + y, list(x = x, y = y)) } add_expr_1(one(0, 1), one(2, 1))

我们可以使用它来创建一个函数,以将任意数量的术语加在一起:

We can use this to make a function to add together any number of terms:

add_expr <- function(x) Reduce(add_expr_1, x) add_expr(list(one(0, 1), one(1, 1), one(2, 3)))

有了这些片段,最终功能很简单-我们计算出代表的次数,然后对每个powers,coefs和reps组合使用Map()调用一次one():

With these piece in place, the final function is simple - we figure out the number of reps, then use Map() to call one() once for each combination of powers, coefs and reps:

fp <- function(powers, coefs) { # Determine number of times each power is repeated. This is too # clever approach but I think it works reps <- ave(powers, powers, FUN = seq_along) # Now generate a list of expressions using one components <- Map(one, powers, coefs, reps) # And combine them together with plus add_expr(components) } powers <- c(-1, 0, 0.5, 0.5, 3) coefs <- c(-1.5, -14, -13, 6, 1) fp(powers, coefs) # -1.5 * x^-1 + -14 * log(x) + -13 * x^0.5 + 6 * x^0.5 * log(x)^1 + # 1 * x^3

更多推荐

在建立分数多项式函数时避免使用eval(parse())

本文发布于:2023-10-30 23:48:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1544363.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多项式   函数   分数   parse   eval

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!