任意阶次多项式的函数(首选符号方法) [英] Function for polynomials of arbitrary order (symbolic method preferred)
问题描述
R <-c(0.256,0.512,0.768,1.024 ,1.28,1.437,1.594,1.72,1.846,1.972,2.098,2.4029)
Ic <-c(1.78,1.71,1.57,1.44,1.25,1.02,0.87,0.68,0.54,0.38,0.26,0.17 )
NN < - 3
ft -lm(Ic-poly(R,NN,raw = TRUE))
pc < - coef(ft)
所以我可以创建一个多项式函数:
f1 < - 函数(x)pc [1] + pc [2] * x + pc [3] * x ^ 2 + pc [4] * x ^ 3
举例来说,取一个衍生物:
g1 < - Deriv(f1)
如何创建一个通用函数不必为每个新的多项式程度重写 NN
?
<我的原始答案可能不是你真正想要的,因为它是数字而非象征性的。这是符号解决方案。
##使用`x`作为变量名称
##取多项式系数
##
##
##可以返回一个字符串或者一个表达式, ; - paste(x,seq_along(pc)-1,sep =^)
stringexpr < - paste(stringexpr,pc,sep =*)
stringexpr< - paste (strictgexpr,collapse =+)
if(expr)return(parse(text = stringexpr))
else return(stringexpr)
}
##使用R基准的D(具有系数0.1,0.2,0.3,0.4
立方<-f(pc = 1:4/10,真))
##的示例三次多项式需要表达式)
dcubic <-D(立方体,名称=x)
#0.2 + 2 * x * 0.3 + 3 * x ^ 2 * 0.4
# #使用`Deriv :: Deriv`
library(Deriv)
dcubic < - Deriv(立方体,x =x,nderiv = 1L)
#表达式(0.2 + x *(0.6 + 1.2 * x))
Deriv(f(1:4/10,FALSE),x =x ,nderiv = 1L)##使用字符串,得到字符串
#[1]0.2 + x *(0.6 + 1.2 * x)
当然, Deriv
使高阶导数更容易获得。我们可以简单地设置 nderiv
。然而,对于 D
,我们必须使用递归(参见?D
)的例子。
Deriv(立方体,x =x,nderiv = 2L)
#表达式(0.6 + 2.4 * x)
Deriv(立方体,x =x,nderiv = 3L)
#表达式(2.4)
Deriv(立方体,x =x,nderiv = 4L)
#表达式(0)
如果我们使用表达式,我们将能够在稍后评估结果。例如,
eval(cubic,envir = list(x = 1:4))##三次多项式
#[1] 1.0 4.9 14.2 31.3
eval(dcubic,envir = list(x = 1:4))##其一阶导数
#[1] 2.0 6.2 12.8 21.8
以上意味着我们可以包装一个函数的表达式。使用函数有几个优点,一个是我们可以使用 curve
或 plot.function
来绘制它。 / p>
fun < - 函数(x,expr)eval.parent(expr,n = 0L)
请注意, fun
的成功需要 expr
作为符号 x
的表达式。例如,如果 expr
定义为 y
,我们需要定义 fun
与
函数(y,expr)
。现在让我们使用 curve
来绘制立方
和 dcubic
,on范围 0 < x < 5
:
curve(fun(x,cubic),from = 0 to to 5) ## colorblack
curve(fun(x,dcubic),add = TRUE,col = 2)## colorred
最方便的方法当然是定义一个单个函数 FUN
而不是执行 f
+ fun
组合。这样,我们也不需要担心 f
和 fun
使用的变量名的一致性。 。
FUN < - function(x,pc,nderiv = 0L){
##检查缺少的参数
if(missing(x)|| missing(pc))stop(arguments missing without default!)
##多项式表达式
stringexpr< - paste(x, seq_along(pc)-1,sep =^)
strictgexpr < - paste(stringexpr,pc,sep =*)
strictgexpr < - paste(stringexpr,collapse =+ )
expr< - parse(text = stringexpr)
##获取导数
dexpr < - Deriv :: Deriv(expr,x =x,nderiv = nderiv)
##评估
val < - eval.parent(dexpr,n = 0L)
##注意,如果我们采用许多衍生工具以使dexpr变成常量
## `val`没有`x`,所以它的长度只有1
##我们需要重复这个常量来匹配`length(x)`
if(length(val)== 1L )val< - rep.int(val,leng th(x))
##现在我们返回
val
}
假设我们要评估一个三次多项式,它的系数 pc <-c(0.1,0.2,0.3,0.4)
及其导数 x< - seq(0,1,0.2)
,我们可以简单地做到:
FUN (x,pc)
#[1] 0.1000 0.1552 0.2536 0.4144 0.6568 1.0000
FUN(x,pc,nderiv = 1L)
#[1] 0.200 0.368 0.632 0.992 1.448 2.000
FUN(x,pc,nderiv = 2L)
#[1] 0.60 1.08 1.56 2.04 2.52 3.00
FUN(x,pc,nderiv = 3L )
#[1] 2.4 2.4 2.4 2.4 2.4 2.4
FUN(x,pc,nderiv = 4L)
#[1] 0 0 0 0 0 0
现在绘图也很容易:
从$ 0到= 5,add = TRUE,
曲线(FUN(x,pc,1))的曲线(FUN(x,pc) (FUN(x,pc,2),from = 0,to = 5,add = TRUE,col = 3)
曲线(FUN(x,pc,3),从= 0到= 5,add = TRUE,col = 4)
I've found polynomial coefficients from my data:
R <- c(0.256,0.512,0.768,1.024,1.28,1.437,1.594,1.72,1.846,1.972,2.098,2.4029)
Ic <- c(1.78,1.71,1.57,1.44,1.25,1.02,0.87,0.68,0.54,0.38,0.26,0.17)
NN <- 3
ft <- lm(Ic ~ poly(R, NN, raw = TRUE))
pc <- coef(ft)
So I can create a polynomial function:
f1 <- function(x) pc[1] + pc[2] * x + pc[3] * x ^ 2 + pc[4] * x ^ 3
And for example, take a derivative:
g1 <- Deriv(f1)
How to create a universal function so that it doesn't have to be rewritten for every new polynomial degree NN
?
My original answer may not be what you really want, as it was numerical rather symbolic. Here is the symbolic solution.
## use `"x"` as variable name
## taking polynomial coefficient vector `pc`
## can return a string, or an expression by further parsing (mandatory for `D`)
f <- function (pc, expr = TRUE) {
stringexpr <- paste("x", seq_along(pc) - 1, sep = " ^ ")
stringexpr <- paste(stringexpr, pc, sep = " * ")
stringexpr <- paste(stringexpr, collapse = " + ")
if (expr) return(parse(text = stringexpr))
else return(stringexpr)
}
## an example cubic polynomial with coefficients 0.1, 0.2, 0.3, 0.4
cubic <- f(pc = 1:4 / 10, TRUE)
## using R base's `D` (requiring expression)
dcubic <- D(cubic, name = "x")
# 0.2 + 2 * x * 0.3 + 3 * x^2 * 0.4
## using `Deriv::Deriv`
library(Deriv)
dcubic <- Deriv(cubic, x = "x", nderiv = 1L)
# expression(0.2 + x * (0.6 + 1.2 * x))
Deriv(f(1:4 / 10, FALSE), x = "x", nderiv = 1L) ## use string, get string
# [1] "0.2 + x * (0.6 + 1.2 * x)"
Of course, Deriv
makes higher order derivatives easier to get. We can simply set nderiv
. For D
however, we have to use recursion (see examples of ?D
).
Deriv(cubic, x = "x", nderiv = 2L)
# expression(0.6 + 2.4 * x)
Deriv(cubic, x = "x", nderiv = 3L)
# expression(2.4)
Deriv(cubic, x = "x", nderiv = 4L)
# expression(0)
If we use expression, we will be able to evaluate the result later. For example,
eval(cubic, envir = list(x = 1:4)) ## cubic polynomial
# [1] 1.0 4.9 14.2 31.3
eval(dcubic, envir = list(x = 1:4)) ## its first derivative
# [1] 2.0 6.2 12.8 21.8
The above implies that we can wrap up an expression for a function. Using a function has several advantages, one being that we are able to plot it using curve
or plot.function
.
fun <- function(x, expr) eval.parent(expr, n = 0L)
Note, the success of fun
requires expr
to be an expression in terms of symbol x
. If expr
was defined in terms of y
for example, we need to define fun
with function (y, expr)
. Now let's use curve
to plot cubic
and dcubic
, on a range 0 < x < 5
:
curve(fun(x, cubic), from = 0, to = 5) ## colour "black"
curve(fun(x, dcubic), add = TRUE, col = 2) ## colour "red"
The most convenient way, is of course to define a single function FUN
rather than doing f
+ fun
combination. In this way, we also don't need to worry about the consistency on the variable name used by f
and fun
.
FUN <- function (x, pc, nderiv = 0L) {
## check missing arguments
if (missing(x) || missing(pc)) stop ("arguments missing with no default!")
## expression of polynomial
stringexpr <- paste("x", seq_along(pc) - 1, sep = " ^ ")
stringexpr <- paste(stringexpr, pc, sep = " * ")
stringexpr <- paste(stringexpr, collapse = " + ")
expr <- parse(text = stringexpr)
## taking derivatives
dexpr <- Deriv::Deriv(expr, x = "x", nderiv = nderiv)
## evaluation
val <- eval.parent(dexpr, n = 0L)
## note, if we take to many derivatives so that `dexpr` becomes constant
## `val` is free of `x` so it will only be of length 1
## we need to repeat this constant to match `length(x)`
if (length(val) == 1L) val <- rep.int(val, length(x))
## now we return
val
}
Suppose we want to evaluate a cubic polynomial with coefficients pc <- c(0.1, 0.2, 0.3, 0.4)
and its derivatives on x <- seq(0, 1, 0.2)
, we can simply do:
FUN(x, pc)
# [1] 0.1000 0.1552 0.2536 0.4144 0.6568 1.0000
FUN(x, pc, nderiv = 1L)
# [1] 0.200 0.368 0.632 0.992 1.448 2.000
FUN(x, pc, nderiv = 2L)
# [1] 0.60 1.08 1.56 2.04 2.52 3.00
FUN(x, pc, nderiv = 3L)
# [1] 2.4 2.4 2.4 2.4 2.4 2.4
FUN(x, pc, nderiv = 4L)
# [1] 0 0 0 0 0 0
Now plotting is also easy:
curve(FUN(x, pc), from = 0, to = 5)
curve(FUN(x, pc, 1), from = 0, to = 5, add = TRUE, col = 2)
curve(FUN(x, pc, 2), from = 0, to = 5, add = TRUE, col = 3)
curve(FUN(x, pc, 3), from = 0, to = 5, add = TRUE, col = 4)
这篇关于任意阶次多项式的函数(首选符号方法)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!