我正在研究微分方程和欧拉方法,但在我的程序中找不到错误。
我们的想法是使用欧拉方法模拟微分方程的估计。
这是我们在课堂上尝试过的一些代码。
# Define differential equation
y.prime.diff.eqn <- function(p, y) {return(5*y-p)}
initial.condition.x1 <- 0
initial.condition.y1 <- 0
# Define Euler Method's estimations
euler <- function(x1 = initial.condition.x1,
y1 = initial.condition.y1,
y.prime = y.prime.diff.eqn(x1, y1),
iter = 5,
step.size = 1) {
for (i in 2:iter)
{
x1[i] <- x1[i-1] + step.size
y1[i] <- y1[i-1] + step.size * (y.prime)
y.prime <- y.prime.diff.eqn(x1[i], y1[i])
}
return(data.frame(cbind(x1,y1)))
}
output <- euler()
output
它会输出正确的结果,但会显示一条警告消息:
Warning message:
In y1[i] <- y1[i - 1] + step.size * (y.prime) :
number of items to replace is not a multiple of replacement length
为什么我会收到此警告?
答案 0 :(得分:0)
你得到奇怪的范围问题,因为函数参数中的函数在体内被调用....并且你认为它在单个值上被调用,例如x1[i]
但它看起来像是在不断增长的向量x1
上调用。只需从迭代函数中取出起始参数,如下所示:
y.prime.diff.eqn <- function(p, y) {return(5*y-p)}
initial.condition.x1 <- 0
initial.condition.y1 <- 0
y.prime = y.prime.diff.eqn(initial.condition.x1, initial.condition.y1)
# Define Euler Method's estimations
euler <- function(x1 = initial.condition.x1,
y1 = initial.condition.y1,
iter = 5,
step.size = 1) {
for (i in 2:iter)
{
x1[i] <- x1[i-1] + step.size
y1[i] <- y1[i-1] + step.size * (y.prime)
y.prime <- y.prime.diff.eqn(x1[i], y1[i])
}
return(data.frame(cbind(x1,y1)))
}
output <- euler()
output
答案相同,没有警告。
答案 1 :(得分:0)
我的一个同学想出了一个没有警告的不同解决方案。
我很想知道在性能方面哪些更好。据我了解,不计算每次迭代的下一个y.prime将是一个改进。但与此同时,我发现斯蒂芬的答案更加整洁。
# Define differential equation
y.prime.diff.eqn <- function(p, y) {return(5*y-p)}
initial.condition.x1 <- 0
initial.condition.y1 <- 0
# Define Euler Method's estimations
euler <- function(x1 = initial.condition.x1,
y1 = initial.condition.y1,
y.prime = y.prime.diff.eqn(x1, y1),
iter = 5,
step.size = 1) {
for (i in 2:iter)
{
x1[i] <- x1[i-1] + step.size
y1[i] <- y1[i-1] + step.size * y.prime.diff.eqn(x1[i-1], y1[i-1)
}
return(data.frame(cbind(x1,y1)))
}
output <- euler()
output