-4

Here is my code for a bisection method. If I input 4 and 5 the program loops infinitely. There is a problem with it running.

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
Adriaan
  • 17,741
  • 7
  • 42
  • 75
loco3424
  • 23
  • 2
  • 6
  • What happens when you step through it in the debugger? – Craig Mar 29 '19 at 13:07
  • @Craig Nothing it just flashes the underline symbol for time – loco3424 Mar 29 '19 at 13:11
  • When you step through a program in the debugger, you should be looking at the values of the variables and tracing the execution of the program to figure out how what it's doing diverges from your expectation of what it should be doing. – Craig Mar 29 '19 at 13:28
  • I don't know what this is actually supposed to do but I can tell, without a debugger, that when you enter 4 and 5 the `Math.Sign(func(c)) = Math.Sign(func(a))` check is going to succeed because both `a` and `c` are positive. Then you set `a = c` and restart the loop, making `a` and `c` still positive, so the check is going to succeed again, and so it goes on... – Visual Vincent Mar 29 '19 at 13:36
  • 1
    And for the record, homework, "schoolwork" or any kind of assignment fall under the same category here. Craig is not just saying random things. Learning how to use the debugger is an essential skill when you start writing complex algorithms as it helps you stop at and step through your code in its different states. – Visual Vincent Mar 29 '19 at 13:39
  • _"so how can i stop it from doing this"_ - As I said I don't know this code's purpose well enough to know what to fix "just like that". – Visual Vincent Mar 29 '19 at 13:43
  • When you get the time I recommend having a look at [Get started with Visual Studio 2017 - Debugging](https://tutorials.visualstudio.com/vs-get-started/debugging) as well as [7 Ways to Look at the Values of Variables While Debugging in Visual Studio](https://devblogs.microsoft.com/devops/7-ways-to-look-at-the-values-of-variables-while-debugging-in-visual-studio/). Merely learning how use breakpoints and how to inspect your variables will help you _**a lot**_ in the future as these are two of the most powerful things you can learn when it comes to solving programming problems. – Visual Vincent Mar 29 '19 at 13:55
  • If you have a counter of every iteration then you could assume the value is not converging on a result after, say, 10,000 tries. I like to call such a counter "sanity", then if you initialise it to 10,000 and decrement it you can check if sanity <= 0, which is mildly amusing sometimes. – Andrew Morton Mar 29 '19 at 16:03

1 Answers1

2

Don't use a GoTo. There's no need. Also, remove the user interaction from the method that does the actual work. Read the data in one place, pass it to a method (usually a Function rather than a Sub) that does the work and returns a result, and then show the result to the user after the function ends.

That makes this question tricky, because the only result we see in the original code is writing "Hello" to the Console, and that's clearly just a debugging statement. What do you want this code to do? (I'm gonna assume you mean 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

And really, it should look like this:

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

and be called like this:

Bisect(a, b, Function(x) x ^ 2 - 2)

Also, the algorithm here is slightly off based the wikipedia article. This is more precise:

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

I bring it up, because the complaint in the original question is this:

the program loops infinently[sic]

and one of the tenants of the algorithm is it's not guaranteed to converge, hence the step counter.

Finally, this looks to me like it might do well as a recursive function. Recursion can improve things here because we can rely on the call stack overflowing rather than needing to implement a step counter:

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

Of course, catching that StackOverflowException is a trick in itself, so you may still want that step counter. But I need to leave something for you to do yourself.

This also helps demonstrate part of why I recommend removing all user I/O from the Bisect() method. If this method were also responsible for talking to the end user, it would not be possible to even consider the recursive option, where the code is clearly far shorter and simpler than any of the others.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I am sorry sorry but the thing is not needed now, my assignemnt was b4 this however still got an A* thank you for this i will check this out – loco3424 Mar 29 '19 at 15:56
  • It's okay. I knew that when I started (didn't see the question until more than an hour after you asked, so it was already too late). I wouldn't have provided so much actual code for a homework question... but with the homework already due, and the chance to use some recursion while I helped you learn some new things (how to structure methods better, introduce recursion), it looked like a fun problem. – Joel Coehoorn Mar 29 '19 at 15:58
  • Yes wasn't homework was for VIVA, but very thank you so much better than people like who are stubbon, yes we did recursions earlier, however this was too much and was struggling. However will try. Thank you – loco3424 Mar 29 '19 at 16:00
  • 2
    @loco3424 asking for help with Uni is fine. But the point of the questions is that they stay on the site after you no longer need them. So please review the answer and if it does answer the question consider marking it with the green tick. –  Mar 29 '19 at 16:11
  • @YvetteColomb sorry i was in my VIVA, no access for computer until now – loco3424 Mar 29 '19 at 16:21
  • @loco3424 that's fine, I'm just getting you familiar with the site and how we work. –  Mar 29 '19 at 16:22
  • 1
    @AndrewMorton Yep, that was a type, fixed. – Joel Coehoorn Mar 29 '19 at 20:44
  • It would probably be a good idea (as I think I implied or even outright stated on one of my comments that got deleted) to verify that there is a sign change in the function between the given bounds. That doesn't guarantee finding a root (the sign change could be due to asymptotic behavior e.g. 1/x) but it does eliminate obvious problems like the 4, 5 issue that was raised originally. – Craig Apr 01 '19 at 15:07