是否有可能在VBA中实现牛顿方法* *

时间:2016-09-18 02:09:15

标签: excel vba excel-vba

我需要在闭包上使用牛顿方法。

Function f (x as Double, y as Double) as Double
    f = x^3-y
End Function

我从一个单元格中获取y的值,然后我想知道f何时为零。在上面的玩具示例中,如果单元格包含y=8,那么我希望Newton的方法能够找到接近x=2的解法。

我的解决方案是制作newton_solve_f函数:

Function newton_solve_f (y as Double as Double) as Double
    Dim x as Double
    x = 0 'initial guess for x
    'do Newton's method to find x
    ...
    newton_solve_f = x
End Function

因此,我将我的牛顿方法代码(taken from here)复制粘贴到newton_solve_f

问题在于我有几个这样的f s(一些有两个以上的参数),如果我没有必须分开几乎相同的{{1}那么它会非常整洁对于他们每个人。

你如何在VBA中解决这个问题?

例如,在Python中,可以按如下方式解决此问题:

newton_solve_f

此处def f(y): def g(x): return x^3-y return g def newton_solve(f): #do newton's method on f(x) newton_solve(f(3)) 是一个函数,一个变量的closure。 (维基百科上的闭包示例几乎与此相同。)

PS。我知道牛顿的方法也需要f(3)的(部分)导数,我实际上做的更像是割线方法,但这与什么无关我问的是

3 个答案:

答案 0 :(得分:1)

闭包不属于VBA。但是您可以在方法范围内使用静态变量。它们不能在方法之外使用。如果您希望变量在外部可见,则必须使用全局变量。优先在模块中声明它是公开的。

我们无法在VB中定义函数内部的函数。试图转换您提到的链接中给出的代码。我希望它对你有所帮助。不熟悉php,但你可以看到下面的方法,并相应地做出改变。

String#to_i!

答案 1 :(得分:0)

首先总结一下:你想要创建一个能找到(使用Newton-Raphson方法)函数根的函数。您已经编写了这些函数并且正在为某些函数工作,但是希望有助于扩展您的代码,以便它可以使用具有不同数量参数的各种函数吗?

我认为您首先需要考虑您希望它涵盖哪些输入功能。如果你只处理多项式(如你的例子所示),这应该是相当简单的。

你可以拥有以下的一般功能:

Function fnGeneralCase (x, y, z, w, a1, a2, a3, b1, b2, b3, c1, c2, c3 as Double) as Double
    fnGeneralCase = a1*x^3 + a2*x^2 + a3*x + b1*y^3 + b2*y^2 + b3*y + c1*z^3 + c2*z^2 + c3*z + w
End Function

Function fnDerivGeneralCase (x, y, z, w, a1, a2, a3, b1, b2, b3, c1, c2, c3 as Double) as Double
    fnDerivGeneralCase = a1*3*x^2 + a2*2*x + a3 + b1*3*y^2 + b2*2*y + b3 + c1*3*z^2 + c2*2*z + c3
End Function

当您不需要时,只需将输入设置为零(大部分时间都是如此)。

所以你的例子叫:

answer = fnGeneralCase(guess, 0, 0, -8, 1, 0, 0, 0, 0, 0, 0, 0, 0)

基本上给出了:

function = x^3-8

如果你想要包含多项式,那么这将变得更加复杂,但你仍然可以使用上述方法......

答案 2 :(得分:0)

这似乎是在提出2个相关问题:

  1. 如何在vba中将函数作为参数传递。
  2. 如何从现有函数中创建闭包。
  3. 不幸的是,这些都不是真正支持的,

    • for 1你通常可以通过传递字符串函数名称并使用' Application.Run'来解决这个问题。调用该函数。
    • 如果你有很多具有不同参数数量的函数,那么
    • 2会比较棘手,但对于一定数量的参数,你可以在newton_solve函数中添加额外的参数,或者使用全局变量。

    e.g。

    Public Function f(x as Double, y as Double) as Double
        f = x^3-y
    End Function
    
    
    Function newton_solve_f (function_name as String, y as Double) as Double
        Dim x as Double
        x = 0 'initial guess for x
        'do Newton's method to find x
    
        ...
           ' invoke function_name
           x = Application.Run(function_name, x, y)
        ...
        newton_solve_f = x
    End Function
    

    假设f在名为' Module1'的模块中。你可以用这个来打电话:

    x = newton_solve('Module1.f', 3)
    

    请注意,您要呼叫的功能必须是公开的。