另一个函数中的局部变量如何影响我的main函数中的变量?

时间:2017-05-20 02:41:03

标签: vba variables

所以我有一个调用辅助功能(AllODEs)的“主”功能(SolveSixODES)。当它这样做时,main函数中的x值会被修改。我不明白这是怎么可能的,因为它不是一个全局变量。

这是代码,我使用的输入如下:

x = 0,xmax = 3,y = 0-6,h = 0.1,误差= 0.1

Public Function SolveSixODE(x As Double, xmax As Double, Y As Range, h As Double, error As Double) 'Weird bug: You must leave the first y4 value blank

Dim i As Integer, k(7, 7) As Double, j As Integer, m As Integer                                             'k(Order #, equation #)
Dim Y5(7) As Double, Y4(7) As Double, Y4Old(7) As Double
Dim delta0(7) As Double, delta1(7) As Double, delRatio(7) As Double, Rmin As Double

For i = 1 To 6                  'Moving the input data so it can acutally be used
    Y4(i) = Y(i)
Next i

While x < xmax

    If x + h < xmax Then
        x = x + h
    Else
        h = xmax - x
        x = xmax
    End If

    For j = 1 To 6                                                          'j is the order i is equation number
        For i = 1 To 6                                                      'Calculating all of the k(1) values for eq 1 to 6
            k(j, i) = AllODES(x, Y4, i, j, k, h)    '!!!!!SOME HOW THIS LOOP MAKES X negative...!!!!!!!
        Next i
    Next j

    For i = 1 To 6
        Y4Old(i) = Y4(i)                                                    'Saving old y4 value to calc delta0
        Y4(i) = Y4(i) + h * (k(1, i) * (37 / 378) + k(3, i) * (250 / 621) + k(4, i) * (125 / 594) + k(6, i) * (512 / 1771))
        Y5(i) = Y4(i) + h * (k(1, i) * (2825 / 27648) + k(3, i) * (18575 / 48384) + k(4, i) * (13525 / 55296) + k(5, i) * (277 / 14336) + k(6, i) * (0.25))

        delta0(i) = error * (Abs(Y4Old(i)) + Abs(h * AllODES(x, Y4Old, i, 1, k, h)))  'First order because we don't want to use the k vals
        delta1(i) = Abs(Y5(i) - Y4(i))
        delRatio(i) = Abs(delta0(i) / delta1(i))                                'Ratio of errors
    Next i

    Rmin = delRatio(1)

    For i = 2 To 6
        If delRatio(i) < Rmin Then
            Rmin = delRatio(i)                                              'Determine the smallest error ratio
        End If
    Next i

    If Rmin < 1 Then                                                        'If this is true then the step size was too big must repeat step
        x = x - h                                                           'Set x and y's back to previous values
        For i = 1 To 6
            Y4(i) = Y4Old(i)
        Next i
        h = 0.9 * h * Rmin ^ 0.25                                           'adjust h value; 0.9 is a safety factor
    Else
        h = 0.9 * h * Rmin ^ 0.2                                            'Otherwise, we march on
    End If
    m = m + 1
Wend

SolveSixODE = Y4

End Function

Public Function AllODES(x As Double, Y() As Double, EqNumber As Integer, order As Integer, k() As Double, h As Double) As Double

Dim conc(7) As Double, i As Integer, j As Integer

If order = 1 Then
    x = x - h
    For i = 1 To 6                                              'Movin the data so I can use it
        conc(i) = Y(i)                                          'also adjusting the x and y values for RK4 (Cash Karp values)
    Next i

ElseIf order = 2 Then
    x = x - h + h * 0.2
    For i = 1 To 6
        conc(i) = Y(i) + h * k(1, i) * 0.2
    Next i

ElseIf order = 3 Then
    x = x - h + 0.3 * h
    For i = 1 To 6
        conc(i) = Y(i) + h * (0.075 * k(1, i) + 0.225 * k(2, i))
    Next i

ElseIf order = 4 Then
    x = x - h + 0.6 * h
    For i = 1 To 6
        conc(i) = Y(i) + h * (0.3 * k(1, i) - 0.9 * k(2, i) + 1.2 * k(3, i))
    Next i

ElseIf order = 5 Then
    x = x - h + h
    For i = 1 To 6
        conc(i) = Y(i) + h * ((-11 / 54) * k(1, i) + 2.5 * k(2, i) - (70 / 27) * k(3, i) + (35 / 27) * k(4, i))
    Next i

ElseIf order = 6 Then
    x = x - h + 0.875 * h
    For i = 1 To 6
        conc(i) = Y(i) + h * ((1631 / 55296) * k(1, i) + (175 / 512) * k(2, i) + (575 / 13824) * k(3, i) + (44275 / (110592) * k(4, i) + (253 / 4096) * k(5, i)))
    Next i
Else
    MsgBox ("error")
End If


If EqNumber = 1 Then                                            'These are the actual equations
    AllODES = x + Y(1)

ElseIf EqNumber = 2 Then
    AllODES = x

ElseIf EqNumber = 3 Then
    AllODES = Y(3)

ElseIf EqNumber = 4 Then
    AllODES = 2 * x

ElseIf EqNumber = 5 Then
    AllODES = 2 * Y(2)

ElseIf EqNumber = 6 Then
    AllODES = 3 * x

Else
    MsgBox ("You entered an Eq Number that was dumb")
End If

End Function

这可能是我错过了一些非常微不足道的东西,但这似乎与我对变量如何运作的知识相矛盾。因此,如果您了解在这种情况下函数如何能够操纵另一个函数的变量,我将不胜感激任何建议和/或解释!

提前致谢!

1 个答案:

答案 0 :(得分:3)

  

主函数中的x值被修改。我不明白这是怎么可能的,因为它不是一个全局变量

这是正常的,因为您将x 通过引用传递给函数AllODES,并且您确实在那里进行了更改。如果未在function / sub原型中明确指定关键字ByVal,则默认传递机制为ByRef,即引用

Public Function AllODES(x As Double, ...

装置

Public Function AllODES(ByRef x As Double, ....

我们发现在此函数中操作x ,因此更改将在调用方中显示。如果您希望x的更改不在调用者的范围内报告,请按值传递x

Public Function AllODES(ByVal x As Double, ....
'                       ^^^^^

仅在这种情况下,调用者的x和被调用者的x将是两个不同的变量。