To graph a function we need to evaluate a string into its math equivalent. Excel VBA has the Application.Evaluate method which takes a variant for an argument and will evaluate a wide range of math symbols, with or without quotations – whatever is between the parentheses. In Visual Studio that doesn’t exist. We want to type a function (the right side of Y = some expression of X) into a textbox on a form, save it to a string variable, then calculate the value to a double for a range of X values. For instance,
strfunc = “X^3 – 3*X^2 + 2*x + 2”
A loop calculates X and Y values starting at X minimum, incrementing by a small X increment, ending at X maximum, and saving all the values to an array to be an argument for AddLightWeightPolyline.
the number of points to be stitched into a graph is calculated –
numpts = CInt((Xmax – Xmin) / Xinc) ‘number of line segments
there is always one more point than line segments
numpts = numpts + 1
the array of doubles is sized –
ReDim Pt(0 To numpts * 2 – 1) ‘store x and y for one pt
after the number of points has been calculated, and the array is ready, the loop is
For i = 1 To numpts x = Xmin + ((i - 1) * Xinc) y = eval_func(strfunc, x) pt(i * 2 - 2) = x pt(i * 2 - 1) = y Next i
X is recalulated each time through the loop. Rather than adding the increment to a running sum, its more accurate to use the loop counter to multiply the increment, because of the imprecision of doubles. With odd numbers you might eventually run one cycle short or long. The loop counter should always be an integer. Calculation of Y is handed off to a function with the function string and the current value of X. The function substitutes the numerical value of X whereever X the symbol appears.
Debug.Print strfunc
strfunc = Replace(strfunc, “x”, x, , , vbTextCompare)
Debug.Print strfunc
the first time thru where X is at the starting value of, say, -6, the string and the modified string look like –
X^3 – 3*X^2 + 2*x + 2
-6^3 – 3*-6^2 + 2*-6 + 2
then the final scalar value is calculated and the value returned as Y.
dbl_result = Evaluate(strfunc)
This code was being run from Excel. Evaluate was a method of the top level Application.
For Visual Studio VB.Net we need a replacement for Evaluate.
A lot of people have asked this question. There are quite a few homebuilt parser class solutions. Another method is to link to another language and use its Eval method. A quick easy solution was found, credit to user kleinma
As kleinma says, “Set a reference in your app to “Microsoft Script Control 1.0″ It is under the COM tab in references, not in the .NET tab”
A lot of testing will show if its a decent fix or just the first try.
Public Xmin As Double Public Xmax As Double Public Xinc As Double Public Ylim As Double Public g_stop As Boolean Public g_err_counter As Integer Function calc_xy(strfunc As String) As Double() 'returns an array of x and y doubles 'Xmax, Xmin, Xinc, Ylim are all assumed to have values Dim x, y As Double Dim i, numpts As Integer Dim Pt() As Double g_err_counter = 0 g_stop = False numpts = CInt((Xmax - Xmin) / Xinc) 'number of line segments numpts = numpts + 1 'one more pt than line segment ReDim Pt(0 To numpts * 2 - 1) 'store x and y for one pt For i = 1 To numpts x = Xmin + ((i - 1) * Xinc) y = eval_func(strfunc, x) If g_stop Then 'if eval_func set g_stop then MsgBox("errorcounter at 3 - exiting") Exit For End If Pt(i * 2 - 2) = x Pt(i * 2 - 1) = y Next i Return Pt End Function Function eval_func(ByVal strfunc As String, x As Double) As Double 'returns a double 'on error returns Ylim but sets a flag to stop after 3 errors 'which would indicate a bad formula 'one or two error is ok because havent solved the mid-graph asymptote yet Dim result As Double strfunc = Replace(strfunc, "x", x.ToString, , , vbTextCompare) Dim SC As New MSScriptControl.ScriptControl SC.Language = "VBSCRIPT" Try result = Convert.ToDouble(SC.Eval(strfunc)) Catch ex As Exception MessageBox.Show(ex.GetType.ToString & " " & ex.Message) g_err_counter = g_err_counter + 1 If g_err_counter > 2 Then g_stop = True End If result = Ylim End Try Return result End Function