Find closest number-VBForums

1. ## 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. ## 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. ## 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.

4. ## 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. ## 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. ## 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.

7. ## 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.

8. ## 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. ## 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. ## 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. ## 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.

12. ## 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. ## 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