如何在R中解决这样的符号函数

时间:2014-03-04 21:14:42

标签: r

对于有经验的人来说,这应该很简单。 我想用R解决方程式。我知道你可以解决 使用Solve()的不同线性/二次方程。

但我有这样的事情:

1/20 = 1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x))

在这种情况下如何解决x?它不能手工完成。 它需要一些数字方法来解决这个问题,就像在TI83中一样。

有没有简单快捷的方法在R中执行此操作而无需编写代码行? 谢谢!

2 个答案:

答案 0 :(得分:5)

正如你所说,确实存在根源。首先是绘制函数:

f <- function(x) {1/20 - 1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x))}
x <- seq(-100,100)
par(mar=c(2,2,1,2))     # this just minimizes plot margins
plot(x,f(x), type="l")
abline(0,0,col="blue",lty=2)

很明显,f(x)确实越过了0次。

下一步是估算过境点。一种方法是查找符号的变化:

x <- seq(-75,0,0.001)
y <- sign(f(x))                     # vector of +1 or -1
plus.to.minus <- which(diff(y)<0)   # diff(y)<0 when f crosses from (+) to (-)
minus.to.plus <- which(diff(y)>0)   # diff(y)>0 when f crosses from (-) to (+)
# first two roots are (+) to (-); third is (-) to (+)
lower <- c(plus.to.minus[1:2],minus.to.plus[3])
roots <- sapply(lower,function(i)uniroot(f,interval=c(x[i],x[i+1]))$root)
lapply(roots,function(x) points(roots,c(0,0,0),col="red",pch=16))
roots
# [1] -67.38961 -41.72593 -10.38446

此代码尝试查找x更改符号的f(x)。实际上有f(x)可能改变符号的两个原因:根或渐近线。在你的情况下,有三个根和三个渐近线。这里的成功取决于在x中有足够小的增量,这样你就不会完全错过一个交叉点。根据上图,看起来0.001足够小。

这里,y是一个向量,它包含x在-75和0之间的符号f(为+1或-1),增量为0.001。通过检查上图来选择极限(-75,0)。我们可以直观地看到有三个根。前两个从(+)到( - )交叉,第三个从( - )到(+)交叉。因此,我们确定交叉发生的x的索引(使用which(...)),然后创建一个包含plus.to.minus的前两个元素和minus.to.plus的第三个元素的向量。然后我们使用uniroot(...)来调用increment=c(x[i],x[i+1]),其中i是相应交叉点的索引。

最后,我们绘制结果以确认我们实际上找到了根。这非常重要 - 总是总是绘制结果。事实证明,uniroot(...)会找到一个存在渐近线的“根”,所以你必须确保找到了实际的根。

答案 1 :(得分:2)

使用uniroot()求解一个变量中的方程式:

f <- function(x){
  1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x)) - 1/20
}
uniroot(f, interval = c(-1e+08, 1e+08))

请注意,在函数f中,我减去了1/20。这是因为uniroot()找到了函数的零。

在这种情况下,您将收到错误:

Error in uniroot(f, interval = c(-1e+08, 1e+08)) : 
  f() values at end points not of opposite sign

要纠正这个问题,你需要确保零​​存在,如果存在,移动间隔,(a,b)使f(a)== -f(b)