对于有经验的人来说,这应该很简单。 我想用R解决方程式。我知道你可以解决 使用Solve()的不同线性/二次方程。
但我有这样的事情:
1/20 = 1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x))
在这种情况下如何解决x?它不能手工完成。 它需要一些数字方法来解决这个问题,就像在TI83中一样。
有没有简单快捷的方法在R中执行此操作而无需编写代码行? 谢谢!
答案 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)