Find closest number-VBForums
Results 1 to 13 of 13

Thread: Find closest number

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Find closest number

    I am making a program that deals with basic algebraic functions. The following function is meant to calculate the value of x given a certain value of y. The problem is that the answer can't be exact, so I need to figure out how to find the closest number. I thought rounding would work, but it doesn't.

    Code:
    Private Sub cmdX_Click()
        Dim math As New clsMathParser
        Dim x As Single
        
        If lstEqu.Text = vbNullString Then
            MsgBox "You need to select an equation from the list.", vbCritical
            Exit Sub
        End If
        
        math.StoreExpression lstEqu.Text
        For x = xmin To xmax Step 0.001
            If Round(math.Eval1(x), 3) = Val(txtY) Then
                txtX = x
                Exit For
            End If
        Next x
    End Sub

  2. #2
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    7,700

    Re: Find closest number

    Seems like an odd way to go about it? Normally if you know the value of Y then you would plug Y into your equation and the result would be the value of X. It seems that stepping up the value of x in a loop and testing to see if it is equal to Y is just guessing.

  3. #3
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,326

    Re: Find closest number

    How do you know that the range of X values will give a result which will satisfy the equation for a given value of Y ?

    eg take the equation Y = (X / 2) -10
    If you wanted to find X for Y = 20 and your X range was 0 to 10 you'd never get a result.

    You could, instead of rounding, check if the calculated value of Y was within a given tolerance of the required Y

    eq
    Code:
    Dim math As New clsMathParser
    Dim x As Single
    Dim y As Single
    For x = xmin To xmax Step 0.001
        y = math.Eval1(x)
        If y => CSng(txtY.Text) - 0.0005 And y =< CSng(txtY.Text) + 0.0005 Then
            txtX.Text = CStr(x)
            Exit For
        End If
    Next x
    in the above you will get a result if the calculcated value of y is inclusively within + or - 0.0005 of the value desired.
    Last edited by Doogle; Feb 24th, 2012 at 12:29 AM. Reason: Changed the example equation

  4. #4

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Re: Find closest number

    Seems like an odd way to go about it? Normally if you know the value of Y then you would plug Y into your equation and the result would be the value of X.
    Yeah that's how a person might do it, but to program it that way would be very hard because instead of having the x value which is easy to convert the right side of the equation to polish notation and then evaluate, you have the y value so it's seems easier to just brute force it. (Unless maybe im missing something?)

    How do you know that the range of X values will give a result which will satisfy the equation for a given value of Y ?
    I don't, but it's a graphing utility so the user is meant to enter the xmin and xmax correctly lol.

    Whenever I enter zero for y, I get -10 using your example with any equation and I can't figure out why.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Re: Find closest number

    I got it to work. I forgot to add the line math.StoreExpression and I also had to reduce the accuracy to 2 decimal places because it was giving me one off answers fairly often with three and I have no idea why.

    Code:
        math.StoreExpression lstEqu.Text
        For X = xmin To xmax Step 0.01
            Y = math.Eval1(X)
            If Y >= CSng(txtY.Text) - 0.005 And Y <= CSng(txtY.Text) + 0.005 Then
                txtX.Text = CStr(Round(X, 2))
                Exit For
            End If
        Next X

  6. #6
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,355

    Re: Find closest number

    You may wish to try FormatNumber () and lock it into a certain number of decimals. For example:
    Code:
    Y = 355 / 113
    MsgBox FormatNumber(Y, 3)
    Note the incredible accuracy of using 355 / 113 to approximate Pi.
    Doctor Ed

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Re: Find closest number

    It still doesn't work how I want. Gives me 0.001 off and if I just add 0.001 most of the time it works, but when checking higher numbers it gives 0.001 too much. I really need this to work. I am going to attach the whole program so someone can test it. The get X button is the problem. To test it add a liner equation (ex 4x-6) and then press get x and it will give you 1.499 instead of 1.5.

    I might even consider paying someone a small amount through paypal if they can figure this out.
    Attached Files Attached Files

  8. #8
    Hyperactive Member Lenggries's Avatar
    Join Date
    Sep 2009
    Posts
    353

    Re: Find closest number

    Your fundamental problem is that you are rounding to the same number of significant figures that you are performing your computations with. However, since rounding takes place at one significant figure higher than that, this means your displayed solution will be impacted by rounding error. To get around that, you merely need to either round to one digit less, or operate at one significant digit more. I assume you can't reduce your displayed digit, so that makes the decision easy:

    Code:
        txtX = vbNullString
        math.StoreExpression lstEqu.Text
        For X = xmin To xmax Step 0.0001
            Y = math.Eval1(X)
            If Y >= CSng(txtY) - 0.0005 And Y <= CSng(txtY) + 0.0005 Then
                txtX = CStr(Round(X, 3))
                Exit For
            End If
        Next X
    Unfortunately, this adds 10 times as many computations. There are a few ways to address this. Notably, you can clean up the code a little pit by minimizing the processing that take place inside the For loop:

    Code:
        Dim minY As Single
        Dim maxY As Single
    
        minY = CSng(txtY) - 0.0005
        maxY = minY + 0.001
        txtX = vbNullString
        math.StoreExpression lstEqu.Text
        For X = xmin To xmax Step 0.0001
            Y = math.Eval1(X)
            If Y >= minY And Y <= maxY Then
                txtX = CStr(Round(X, 3))
                Exit For
            End If
        Next X
    But if you really want to make it run faster you need to redesign your approach entirely to use things like binary searches or simulated annealing, and you may need to customize this stuff for non-linear functions.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Re: Find closest number

    It doesn't work if I remove the exit for (which I would need to for problems with multiple answers). It gives me the same answer twice.

    Code:
        Dim minY As Single
        Dim maxY As Single
    
        minY = CSng(txtY) - 0.0005
        maxY = minY + 0.001
        'txtX = vbNullString
        txtInfo = vbNullString
        math.StoreExpression lstEqu.Text
        For x = xmin To xmax Step 0.0001
            y = math.Eval1(x)
            If y >= minY And y <= maxY Then
                'txtX = CStr(Round(x, 3))
                txtInfo = txtInfo & Round(y, 4) & vbTab & Round(x, 3) & vbCrLf
            End If
        Next x
    Any ideas? Would I need to change to a binary search to make this work?

  10. #10
    Hyperactive Member Lenggries's Avatar
    Join Date
    Sep 2009
    Posts
    353

    Re: Find closest number

    Of course it gives you the same answer twice. That is a direct consequence of your algorithm. The most obvious way to get around this is to compare rounded results and if they are equal to one another, discard the second result and keep searching. However, you're going to have to figure out how to handle a bevy of problems. For example, take the following quadrilateral equations in which you want to solve for x when y = 0:

    y = x^2 + 1
    If y = 0, x = i (the imaginary unit). Thus, there are no real solutions (give that your algorithm is only searching for roots between -10 and +10, this likely isn't a big deal).

    y = x^2 + 2x + 1 = (x + 1)^2
    Both roots of this quadrilateral are -1. Thus, if you discard redundant results as suggested above, you're going to skip over a root (depending on what you are actually trying to do, this also might not be a problem).

    y = x^2 - 3x + 2.2499999999 = (x - 1.49999)(x - 1.50001)
    In this case there are two separate roots, x = 1.49999 and x = 1.50001. However, the difference between the two roots (0.00002) has more significant figures than your algorithm works with, and thus the differences between them will be rounded and your algorithm will simply return 1.5 for the first root and discard remaining results.

    Frankly, I think it's a bit of a fool's errand to try to program for all possibilities, even on something as seemingly straightforward as this. I suggest you simply make a design decision as to what functionality is important and accept that you will not be able to produce perfect results for all situations.

  11. #11

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Re: Find closest number

    I found someone who was working on a similar program and I emailed him and asked how he did it. He said that he just wrote an algorithm that keeps dividing by two and checking if greater or less than to determine the answer. This seems a lot simpler than this and I think it will give me better results. I think it may take more time to compute though. Do you think I should use this approach?

    Don't know how I'd make it work with multiple answers though.
    Last edited by veebee123; Mar 10th, 2012 at 03:16 PM.

  12. #12
    Frenzied Member
    Join Date
    Nov 2010
    Posts
    1,197

    Re: Find closest number

    the process for solving your equation is called the newton-raphson method

    you simple enter any x value into the derivative of you target equation and feed the output back into the equation untill the input andout put are the same!

    there is a problem with NRM in that it can perform some perfect-oscilations and so not resolve the equation..

    for that reason it is worth while capturing the last pair of outputs to ensure you have not started oscilating.

    There is a paper on this problem, I wrote, that is now taught at OU

    here to help

  13. #13

    Thread Starter
    Lively Member
    Join Date
    Dec 2008
    Posts
    102

    Re: Find closest number

    you simple enter any x value into the derivative of you target equation and feed the output back into the equation untill the input andout put are the same!
    Thanks for the help, but if I use this method, then I also have to write code to find the derivative first.

    Anyone know if I could make the divide by 2 method work with multiple answers?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.