B4J Library [B4X] Eval (expressions evaluator)

The attached class allows you to evaluate mathematical expressions with support for custom functions.
It is compatible with B4A, B4J and B4i.

Example:
B4X:
Sub AppStart (Args() As String)
   Dim e As B4XEval
   e.Initialize(Me, "Eval")
   Log(e.Eval("1 + Min(2, Max(-4, 1), 6)"))
   Log(e.Eval("-(2+5)*(7-3) + Sin(15 + 15) + Cos(30)"))
   Log("Error? " & e.Error)
   Log(e.Eval("-(2+5)*-(7-3)"))
   Log(e.Eval("-((-7-3))"))
   Log(1.321/-2/3.123 + (2 * 2 + 3) + 4)
   Log(e.Eval("1.321/-2/3.123 + (2 * 2 + 3) + 4"))
End Sub

'custom functions implementation
Sub Eval_Function (Name As String, Values As List) As Double
   Select Name 'it will be lower case
     Case "min"
       Dim d As Double = Values.Get(0)
       For Each n As Double In Values
         If n < d Then d = n
       Next
       Return d
     Case "max"
       Dim d As Double = Values.Get(0)
       For Each n As Double In Values
         If n > d Then d = n
       Next
       Return d
     Case "sin"
       Return SinD(Values.Get(0))
     Case Else
       Log("Invalid function: " & Name)
       Dim e As B4XEval = Sender
       e.Error = True
       Return 0
   End Select
End Sub

Note that if you are using it with B4A then call Eval after Activity_Create completes (you can add Sleep(0) instead). Otherwise the Function event will not be raised.

Updates

V2.01 - Fixes an issue with sub-expressions converted to scientific notation (which is not supported).
V2.00 - adds support for custom functions.
 

Attachments

  • B4XEval.zip
    2.9 KB · Views: 1,017
Last edited:

imbault

Well-Known Member
Licensed User
Longtime User
One more thing, if I may, would it be complicated to include variables in expressions like (or something to instantiate variables which can be used in this class):
B4X:
Log(e.Eval(" Max(-4, a)"))
or
B4X:
dim a as int = 10
e.SetVar("VA", a )
Log(e.Eval(" Max(-4, "VA")"))

It would be more than great
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can create a "get" function that returns values from an array:
B4X:
Sub Process_Globals
   Private vars(1000) As Double
End Sub

Sub AppStart (Args() As String)
   Dim e As B4XEval
   e.Initialize(Me, "Eval")
   vars(10) = 100
   Log(e.Eval("1 + Min(2, Max(-4, 1), 6)"))
   Log(e.Eval("-(2+5)*(7-3) + Sin(15 + 15) + Cos(30)"))
   Log("Error? " & e.Error)
   Log(e.Eval("-(2+5)*-(7-3)"))
   Log(e.Eval("-((-7-3))"))
   Log(1.321/-2/3.123 + (2 * 2 + 3) + 4)
   Log(e.Eval("1.321/-2/3.123 + (2 * 2 + 3) + 4"))
   Log(e.Eval("get(10) * 3")) '<-----
End Sub

Sub Eval_Function (Name As String, Values As List) As Double
   Select Name 'it will be lower case
     Case "min"
       Dim d As Double = Values.Get(0)
       For Each n As Double In Values
         If n < d Then d = n
       Next
       Return d
     Case "max"
       Dim d As Double = Values.Get(0)
       For Each n As Double In Values
         If n > d Then d = n
       Next
       Return d
     Case "sin"
       Return SinD(Values.Get(0))
     Case "get"
       Return vars(Values.Get(0)) '<-----
     Case Else
       Log("Invalid function: " & Name)
       Dim e As B4XEval = Sender
       e.Error = True
       Return 0
   End Select
End Sub
 

imbault

Well-Known Member
Licensed User
Longtime User
You can create a "get" function that returns values from an array:
B4X:
Sub Process_Globals
   Private vars(1000) As Double
End Sub

Sub AppStart (Args() As String)
   Dim e As B4XEval
   e.Initialize(Me, "Eval")
   vars(10) = 100
   Log(e.Eval("1 + Min(2, Max(-4, 1), 6)"))
   Log(e.Eval("-(2+5)*(7-3) + Sin(15 + 15) + Cos(30)"))
   Log("Error? " & e.Error)
   Log(e.Eval("-(2+5)*-(7-3)"))
   Log(e.Eval("-((-7-3))"))
   Log(1.321/-2/3.123 + (2 * 2 + 3) + 4)
   Log(e.Eval("1.321/-2/3.123 + (2 * 2 + 3) + 4"))
   Log(e.Eval("get(10) * 3")) '<-----
End Sub

Sub Eval_Function (Name As String, Values As List) As Double
   Select Name 'it will be lower case
     Case "min"
       Dim d As Double = Values.Get(0)
       For Each n As Double In Values
         If n < d Then d = n
       Next
       Return d
     Case "max"
       Dim d As Double = Values.Get(0)
       For Each n As Double In Values
         If n > d Then d = n
       Next
       Return d
     Case "sin"
       Return SinD(Values.Get(0))
     Case "get"
       Return vars(Values.Get(0)) '<-----
     Case Else
       Log("Invalid function: " & Name)
       Dim e As B4XEval = Sender
       e.Error = True
       Return 0
   End Select
End Sub

That's a beginning, what about a set function?

Thanks a lot
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
Would it be very difficult to adapt it so that it would also work with functions that returned other types of data such as strings or dates?
 

agraham

Expert
Licensed User
Longtime User
Do calculations with these values, is it a problem??
No, this is normal and expected. The results are Double values which are binary values that cannot represent accurately every decimal value. If you need exact decimal results you need to use a special library designed to handle decimals like my
 

Ben10

New Member
This is my first time attempting to use a B4X library with B4A. I've created a program in B4J using this library which I would like to run on an Android device using B4A. When attempting to run in B4A the code execution fails and asks if the B4XEval library is missing. Looking at the library in the "AdditionalLibraries/B4X" folder the file type designations are ".b4j". What do i need to do to have this library run successfully in B4A?
 

Ben10

New Member
Thanks, I just did that but now the follow error comes up: "Cannot find: C:\Program Files\Anywhere Software\B4A\libraries\jcore.jar"

Is this because the B4XEval library is dependent on this B4J library?
 

mjcoon

Well-Known Member
Licensed User
Sorry, I was mistaken. B4XEval isn't distributed as a b4xlib. You need to add B4XEval.bas with Project - Add Existing Module.
Thanks I got that to work. But there is no list of operators (in the source) and I easily crash it by using "^", which I thought was quite ordinary.
What I am looking for, unsuccessfully, is

ExpressionEvaluator​

Written by Andrew Graham​

in B4X module form or library...
 

agraham

Expert
Licensed User
Longtime User
It's here
 

mjcoon

Well-Known Member
Licensed User
Thank you Andrew, I had already found file ExpressionEvaluator1.1.zip. Co-incidentally I have for years used your B4PPC library which says: "Overview
This library contains an Evaluator object that is an arithmetic expression evaluator. It supports the arithmetic sub-set of the full Basic4ppc language with a few additions taken from Basic4android. This library requires .NET 2.0 or later and will run on both the desktop and device. This help file describes version 1.1 of the library."
(My B4PPC program correctly shows my age for "3^4"...)
But the content of the zip files does not look like B4X
There is a ExpressionEvaluator1.1source.zip file too which does also not look like B4A
Am I going mad as well as old (a similar age to you, I think...)?
 

mjcoon

Well-Known Member
Licensed User
Have you downloaded the one from the link in my post above? I have and it's definitely the B4A version
Thank you Andrew, yesterday's copy, still in my Downloads folder, is wrong but today's (1) and (2) versions are fine, as you say, and working for me, to evaluate "3^4" correctly!
 
Top