Reputation: 658
I have written a function in VB.NET that uses the Bisect Method
to find a root of an arbitrary function.
[Given a continuous function f(x), if f(x1) and f(x2) have different signs then it guarantees that there is at least one root between x1 and x2. The Bisect Method
narrows the range [x1, x2] until it finds a root.]
I've written the function in 2 different ways: one using a while loop and the other using recursion.
In the while loop method, I could easily keep track of the number of iterations so that, for example, after 1000 loops, if no root has been found, the function stops and exits.
My question here is: How can I insert such a stop condition with the recursion method while still being able to keep tail call optimization? Thank you in advance.
Method 1: While Loop
Public Function FindOneRoot(lowerBound As Double, upperBound As Double, _
tolerance As Double, ByRef Root As Double, _
theFunction As Func(Of Double, Double)) As Boolean
Dim flower As Double = theFunction(lowerBound)
Dim fupper As Double = theFunction(upperBound)
Root = (lowerBound + upperBound) / 2
Dim froot As Double = theFunction(Root)
Dim count As Integer = 0
While Math.Abs(froot) > tolerance
If froot * flower > 0 Then
lowerBound = Root
Else
upperBound = Root
End If
Root = (lowerBound + upperBound) / 2
froot = theFunction(Root)
count += 1 'keep track of the loops
If count >= 1000 Then 'stop looping after 1000 iterations
Exit While
End If
End While
If count < 1000 Then
Return True
Else
Return False
End If
End Function
Method 2: Recursion
Public Function FindOneRoot(x1 As Double, x2 As Double, tolerance As Double, _
theFunction As Func(Of Double, Double)) As Double
Dim x As Double = (x1 + x2) / 2
If Math.Abs(theFunction(x)) < tolerance Then
Return x 'found a root
ElseIf theFunction(x1) * theFunction(x) < 0 Then
Return FindOneRoot(x1, x, tolerance, Root, theFunction)
Else
Return FindOneRoot(x, x2, tolerance, Root, theFunction)
End If
End Function
Upvotes: 1
Views: 1106
Reputation: 4487
Use Same Condition In Recursive. But declare count outside the function
Add Another Parameter as Count pass the count and check inside the function
Public Function FindOneRoot(x1 As Double, x2 As Double, tolerance As Double,
ByRef Root As Double,theFunction As Func(Of Double, Double),
Count as integer) As Boolean
If count >= 1000 Then 'stop looping after 1000 iterations
Return False: Exit Function
End If
Dim x As Double = (x1 + x2) / 2
If Math.Abs(theFunction(x)) < tolerance Then
Return x 'found a root
ElseIf theFunction(x1) * theFunction(x) < 0 Then
Return FindOneRoot(x1, x, tolerance, Root, theFunction,count +1)
Else
Return FindOneRoot(x, x2, tolerance, Root, theFunction,count +1)
End If
End Function
Upvotes: 1