这是我的二等分方法代码。如果我输入4
和5
,则程序将无限循环。运行有问题。
Sub TheBisectionMethod1()
Dim a, b As Double 'Taking two variables, A and B
Console.Write(vbLf & "Input A: ")
a = Double.Parse(Console.ReadLine()) 'This is where user inputs and value stored for A
Console.Write(vbLf & "Input B: ")
b = Double.Parse(Console.ReadLine()) 'This is where user inputs and value stored for B
line1:
Dim c As Double
c = (a + b) / 2 'declearing variable c for the sum of half of the user entered values
If ((Math.Abs(func(c))) < 0.0001) Then 'in flow chart the value of C remians unchange so the program will not run, so it will run if i is >0.0001
Console.Write(vbLf & "C : {0}", c)
ElseIf (Math.Sign(func(c)) = Math.Sign(func(a))) Then
Console.WriteLine("Hello")
a = c
GoTo line1
ElseIf (Math.Sign(func(c)) <> Math.Sign(func(a))) Then
b = c
GoTo line1
End If
End Sub
Function func(x As Double) As Double
Dim y As Double
y = x ^ 2 - 2
Return y
End Function
答案 0 :(得分:2)
不要使用GoTo
。不需要。另外,从执行实际工作的方法中删除用户交互。一次读取数据,将其传递给执行工作并返回结果的方法(通常为Function
而不是Sub
),然后在函数结束后向用户显示结果。
这使这个问题变得棘手,因为我们在原始代码中看到的唯一结果是将"Hello"
写入控制台,并且显然这只是一条调试语句。您要这段代码做什么? (我假设您是说this)
Function Bisect(a as Double, b As Double) As Double
Dim c As Double = (a + b) / 2
Dim d As Double = func(c)
While Math.Abs(d) >= 0.0001
If Math.Sign(d) = Math.Sign(func(a)) Then
a = c
Else
b = c
End If
c = (a + b) / 2
d = func(c)
End While
Return c
End Function
Function func(x As Double) As Double
Return x ^ 2 - 2
End Function
实际上,它应该看起来像这样:
Function Bisect(a as Double, b As Double, f As Function(Of Double, Double)) As Double
Dim c As Double = (a + b) / 2
Dim d As Double = f(c)
While Math.Abs(d) >= 0.0001
If Math.Sign(d) = Math.Sign(f(a)) Then
a = c
Else
b = c
End If
c = (a + b) / 2
d = f(c)
End While
Return c
End Function
并这样称呼:
Bisect(a, b, Function(x) x ^ 2 - 2)
此外,根据维基百科的文章,此处的算法略有偏离。这更精确:
Function Bisect(a as Double, b As Double, f As Function(Of Double, Double)) As Double
Dim TOL As Double = 0.0001
Dim MaxSteps As Integer = 1000
Dim c As Double = (a + b) / 2
While Math.Abs(f(c)) >= TOL AndAlso (b-a)/2 >= TOL AndAlso MaxSteps > 0
If Math.Sign(f(c)) = Math.Sign(f(a)) Then
a = c
Else
b = c
End If
MaxSteps -= 1
c = (a + b) / 2
End While
If MaxSteps = 0 Then
Throw New ArgumentException("The bisection fails to converge within the allowed time for the supplied arguments.")
End If
Return c
End Function
我提出来,因为原始问题中的投诉是这样:
程序无限循环[sic]
并且算法的租户之一不能保证收敛,因此是步数计数器。
最后,在我看来,这似乎很适合作为递归函数。递归可以改善这里的情况,因为我们可以依赖调用堆栈的溢出,而不需要实现步骤计数器:
Function Bisect(a as Double, b As Double, f As Function(Of Double, Double)) As Double
Dim c As Double = (a + b) / 2
If Math.Abs(f(c)) < TOL OrElse (b-a)/2 < TOL Then Return c
If Math.Sign(f(c)) = Math.Sign(f(a)) Then
Return Bisect(c, b, f)
Else
Return Bisect(a, c, f)
End If
End Function
当然,捕获StackOverflowException本身就是一个技巧,因此您可能仍需要该计数器。但是我需要离开某事让你自己做。
这也有助于说明为什么我建议从Bisect()
方法中删除所有用户I / O的部分原因。如果此方法还负责与最终用户对话,则甚至无法考虑递归选项,因为该代码显然比其他任何代码都短且简单。