Excel RK4 VBA函数的困难。函数只返回#REF!价值

Excel RK4 VBA函数的困难。函数只返回#REF!价值,excel,vba,differential-equations,ref,runge-kutta,Excel,Vba,Differential Equations,Ref,Runge Kutta,不适用。不再是问题……试试这个: Function dCdt(y As Variant) As Variant dCdt = ((0.02) - (0.1) * (y)) End Function Function SIMRK44(ByVal x0 As Double, ByVal y0 As Double, ByVal n As Integer, ByVal xtarg As Double) As Double Dim k1 As Double, k2 As Double,

不适用。不再是问题……

试试这个:

Function dCdt(y As Variant) As Variant
    dCdt = ((0.02) - (0.1) * (y))
End Function

Function SIMRK44(ByVal x0 As Double, ByVal y0 As Double, ByVal n As Integer, ByVal xtarg As Double) As Double

    Dim k1 As Double, k2 As Double, k3 As Double, k4 As Double
    Dim ym As Double, ym2 As Double, ye As Double
    Dim Slope As Double, yi As Double, xi As Double, h As Double

    h = (xtarg - x0) / n
    xi = x0
    yi = y0

    For i = 1 To n
        'apply Euler Method to get y at the end of the interval
        k1 = dCdt(yi)
        ym = yi + k1 * h / 2#

        k2 = dCdt(ym)
        ym2 = yi + k2 * h / 2#

        k3 = dCdt(ym2)
        ye = yi + k3 * h

        k4 = dCdt(ye)

        Slope = (1 / 6#) * (k1 + 2# * k2 + 2# * k3 + k4)

        yi = yi + Slope * h
        xi = xi + h
    Next i

    SIMRK44 = yi
End Function
主要问题是名称
RK44
指的是一个单元格,因此Excel会感到困惑。将函数重命名为
SIMRK44
,问题就会消失

我对代码进行了调整,使其成为一个真实的模拟,其中每个步骤的结果取决于前一步。您的代码中出现了一些与不需要的
yold
的混淆

为了更好的可读性,我使用了文字,每个值应该是一个实系数而不是整数。所以
2
而不是
2
。不管怎样,编译器在内部进行了更改,
1/6
不是整数除法

此外,VBA默认将函数参数传递给
ByRef
,这可能会导致副作用。必须在每个参数之前放置
ByVal
,以向Excel显示函数不会修改参数。只有这样,它才能用作自定义项


如果我被要求编写一个
RK4
积分器,那么我会坚持使用教科书中给出的标准伪代码。更简单,更容易理解目的是什么

Function f(ByVal x As Double, ByVal y As Double) As Double
    f = 0.02 - 0.1 * y
End Function

Function SIMRK4(ByVal x0 As Double, ByVal y0 As Double, ByVal n As Long, ByVal xtarg As Double) As Double
    Dim xi As Double, yi As Double, h As Double
    Dim k1 As Double, k2 As Double, k3 As Double, k4 As Double
    h = (xtarg - x0) / n

    xi = x0
    yi = y0

    Do
        'Ensure we don't overstep
        If xi + h > xtarg Then
            h = xtarg - xi
        End If
        k1 = f(xi, yi)
        k2 = f(xi + h / 2#, yi + h / 2# * k1)
        k3 = f(xi + h / 2#, yi + h / 2# * k2)
        k4 = f(xi + h, yi + h * k3)

        xi = xi + h
        yi = yi + (h / 6#) * (k1 + 2# * k2 + 2# * k3 + k4)
    Loop Until xi = xtarg
    SIMRK4 = yi
End Function

另外,上面的代码可以处理可变的时间步长,因为迭代次数不是固定的。

要调试函数,请从VBA sub调用它,然后可以看到问题所在。如果您可以为RK44Lol提供示例参数,那么这也是非常有用的,主要问题是函数名!看看我的答案。