我正在执行迭代计算,以检查y
在R中x
上的变化。我的目标是估计x截距。现在,每个迭代的计算量都很大,因此实现该迭代所需的迭代次数越少越好。
这里是y
与x
相对的图像
我通过定义一个渐近函数来创建一个工作示例,该函数可以充分捕捉问题所在
y <- (-1/x)+0.05
在绘制时会产生
x <- 1:100
y <- (-1/x)+0.05
DT <- data.frame(cbind(x=x,y=y))
ggplot(DT, aes(x, y)) + geom_point() + geom_hline(yintercept=0, color="red")
我已经开发了两个迭代算法来近似x截距。
解决方案1 :x
最初很小,被步进1...n
次。步骤的大小是预先定义的,从大开始(增加10倍)。在每个步骤之后,将计算y.i
。如果abs(y.i) < y[i-1]
,则重复该大步骤,除非y.i
更改符号,这表示该步骤超出了x截距。如果算法超调,则我们回溯并采取较小的步骤(增加2倍)。每次超调时,步长都会从10 *,2 *,1.1 *,1.05 *,1.01 *,1.005 *,1.001 *减小。
x.i <- x <- runif(1,0.0001,0.001)
y.i <- y <- (-1/x.i)+0.05
i <- 2
while(abs(y.i)>0.0001){
x.i <- x[i-1]*10
y.i <- (-1/x.i)+0.05
if(abs(y.i)<abs(y[i-1]) & sign(y.i)==sign(y[i-1])){
x <- c(x,x.i); y <- c(y,y.i)
} else {
x.i <- x[i-1]*2
y.i <- (-1/x.i)+0.05
if(abs(y.i)<abs(y[i-1]) & sign(y.i)==sign(y[i-1])){
x <- c(x,x.i); y <- c(y,y.i)
} else {
x.i <- x[i-1]*1.1
y.i <- (-1/x.i)+0.05
if(abs(y.i)<abs(y[i-1]) & sign(y.i)==sign(y[i-1])){
x <- c(x,x.i); y <- c(y,y.i)
} else {
x.i <- x[i-1]*1.05
y.i <- (-1/x.i)+0.05
if(abs(y.i)<abs(y[i-1]) & sign(y.i)==sign(y[i-1])){
x <- c(x,x.i); y <- c(y,y.i)
} else {
x.i <- x[i-1]*1.01
y.i <- (-1/x.i)+0.05
if(abs(y.i)<abs(y[i-1]) & sign(y.i)==sign(y[i-1])){
x <- c(x,x.i); y <- c(y,y.i)
} else {
x.i <- x[i-1]*1.005
y.i <- (-1/x.i)+0.05
if(abs(y.i)<abs(y[i-1]) & sign(y.i)==sign(y[i-1])){
x <- c(x,x.i); y <- c(y,y.i)
} else {
x.i <- x[i-1]*1.001
y.i <- (-1/x.i)+0.05
}
}
}
}
}
}
i <- i+1
}
解决方案2 :此算法基于Newton-Raphson方法的思想,其中步骤基于y
中的变化率。变化越大,采取的步骤越小。
x.i <- x <- runif(1,0.0001,0.001)
y.i <- y <- (-1/x.i)+0.05
i <- 2
d.i <- d <- NULL
while(abs(y.i)>0.0001){
if(is.null(d.i)){
x.i <- x[i-1]*10
y.i <- (-1/x.i)+0.05
d.i <- (y.i-y[i-1])/(x.i-x[i-1])
x <- c(x,x.i); y <- c(y,y.i); d <- c(d,d.i)
} else {
x.i <- x.i-(y.i/d.i)
y.i <- (-1/x.i)+0.05
d.i <- (y.i-y[i-1])/(x.i-x[i-1])
x <- c(x,x.i); y <- c(y,y.i); d <- c(d,d.i)
}
i <- i+1
}
y.i
的足够小的值上)答案 0 :(得分:1)
根据@Lyngbakr和@LutzL的阅读建议和建议,被称为Brent's Method的寻根算法被证明是有效的,并且比我的Newton-Raphson的实现要快得多(解决方案2)。该算法由uniroot
中的R
实现。
f <- function(x){(-1/x)+0.05}
uniroot(f, interval=c(0,100), maxiter=100)