繁体   English   中英

在R中找到两个根之间的距离

[英]To find the distance between two roots in R

假设我有一个在间隔I上定义好的函数f(x)。我想找到f(x)的最大和最小根,然后取它们的差。 有什么好的编程方法?

确切地说,f在最坏的情况下可能是一个有理函数,如(1 + x)/(1-x)。 大多数时候,它应该是(高次)多项式。 我只需要在某种程度上精确地知道结果。

我在考虑以下方面:

  1. 将f(x)转换为R可以识别的形式。(我可以)

  2. 使用R列出I上f(x)的所有根(我发现uniroot函数仅给我一个根)

  3. 使用R查找列表中的最大和最小元素(将其转换为向量后应该可以)

  4. 取二根之差。 (应该是微不足道的)

我被困在步骤(2)上,我不知道该怎么办。 我的教授给出了一种残酷的解决方案,建议我这样做:

  1. 将间隔I分为一百万个。

  2. 在每个端点上评估f,找到f> = 0的端点。

  3. 从步骤2中形成的集合中选择最大和最小元素。

  4. 拿他们之间的区别。

我觉得这种方法效率不高,一般来说可能不适用于所有f,但是即使对于二次运算,我也难以实现。 我也不知道如何执行步骤(2)。 所以我想问一个提示或一些玩具的例子。


此时,我正在尝试实现以下代码:

Y=rep(0,200)
dim(Y)=c(100,2)
for(i in 1:100){
X=rnorm(9,0,1)
Z=rnorm(16,0,1)
a=0.64
b=a*sum(Z^2)/sum(X^2)
root_intervals <- function(f, interval, n = 1e6) {
    xvals <- seq(interval[1], interval[2], length = n)
    yvals <- f(xvals)
    ypos <- yvals > 0
    x1 <- which(tail(ypos, -1) != head(ypos, -1))
    x2 <- x1 + 1
    ## so all the zeroes we can see are between x1 and x2
    return(cbind(xvals[x1], xvals[x2]))
}

在这里一切正常,但是当我尝试通过以下方式将根提取到Y [i,1],Y [i,2]时:

Y[i,1]=(ri<-root intervals(function(x)(x/(a*x+b))^{9/2}*(1/((1-a)+a*(1-a)/b*x))^4-0.235505, c(0,40),n=1e6)[1]

我发现我无法对其进行评估。 R不断告诉我

Error: unexpected symbol in:
"}
Y[i,1]=(ri<-root intervals"

我被卡住了。 当我感到迷茫时,我非常感谢大家的帮助。

我使用plot函数多次检查了函数的表达式,并且没有语法错误。 我也相信间隔中所有X的定义都很好。

这应该为您提供蛮力解决方案的良好开端。 没错,这并不优雅,但是对于相对简单的单变量函数而言,评估一百万点是微不足道的。

root_intervals <- function(f, interval, n = 1e6) {
    xvals <- seq(interval[1], interval[2], length = n)
    yvals <- f(xvals)
    ypos <- yvals > 0
    x1 <- which(ypos[-1] != head(ypos, -1))
    x2 <- x1 + 1
    ## so all the zeroes we can see are between x1 and x2
    return(cbind(xvals[x1], xvals[x2]))
}

此函数返回x值的两列矩阵,其中该函数在第1列和第2列之间更改符号:

f1 <- function (x) 0.05 * x^5 - 2 * x^4 + x^3 - x^2 + 1

> (ri <- root_intervals(f1, c(-10, 10), n = 1e6))
           [,1]       [,2]
[1,] -0.6372706 -0.6372506
[2,]  0.8182708  0.8182908

> f1(ri)
              [,1]          [,2]
[1,] -3.045326e-05  6.163467e-05
[2,]  2.218895e-05 -5.579081e-05

Wolfram Alpha按指定的时间间隔确认结果。

顶部和底部将是找到的最小和最大间隔。 这些间隔(函数改变符号的interval )正是uniroot想要的interval ,因此您可以使用它来求解(更多)确切的根。 当然,如果函数在一个时间间隔(或任何偶数次)内两次更改符号,它将不会被拾取,因此请选择大n

对已编辑问题的答复:

看起来您试图定义一堆函数,但是您的编辑存在语法错误。 这是我认为您要尝试执行的操作:(第一部分可能需要更多工作才能正常工作)

my_funs <- list()
Y=rep(0,200)
dim(Y)=c(100,2)
for(i in 1:100){
  X=rnorm(9,0,1)
  Z=rnorm(16,0,1)
  a=0.64
  b=a*sum(Z^2)/sum(X^2)
  my_funs[[i]] <- function(x){(x/(a*x+b))^{9/2}*(1/((1-a)+a*(1-a)/b*x))^4-0.235505}
}

这是在您生成的第一个函数上使用root_intervals。

> root_intervals(my_funs[[1]], interval = c(0, 40))
           [,1]       [,2]
[1,]  0.8581609  0.8582009
[2,] 11.4401314 11.4401714

注意输出矩阵 ,函数的根在第一和第二列之间。 作为矩阵,您不能将其分配给向量。 如果要使用单个根, uniroot每行中使用uniroot设置上限和下限。 这留给读者练习。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM