B4A Library ExpressionEvaluator library

I've been meaning to do this for my own use for a while and I have finally got a round tuit that allowed me to get on with it. Everyone should have a round tuit - they are so useful! :)

This is the recursive descent parser from my BasicLib library stripped down to deal with arithmetic functions only. Pass it a valid arithmetic expression as a string and it will return the result. Use a help viewer to see what is supported but basically it will evaluate any arithmetic expression that Basic4android can. It also supports variables that may be used to pass values and store intermediate results.


EDIT :- Version 1.1 has improved error reporting. See post #3 for details.
 

Attachments

  • aroundtuit.jpg
    aroundtuit.jpg
    23 KB · Views: 957
  • ExpressionEvaluator1.1.zip
    15.3 KB · Views: 1,759
Last edited:

agraham

Expert
Licensed User
Longtime User
I realised that with a trivial reorganisation of part of the code I could provide better error handling without impacting performance by adding extra checks.

Version 1.1 now posted should hopefully give a sensible understandable error message under all circumstances. If it doesn't then please post the expression that breaks it and I'll fix it.
 

Informatix

Expert
Licensed User
Longtime User
Thanks for this library. It's very useful.
In my new project, I'd need two more functions: CEIL(n) and DICE(number,sides). Could you add it? DICE could be coded like this:
B4X:
   // r = number of dice, s = sides
        int result = 0;
        for (int i=0; i < r; i++) {
           result = result + Math.floor((Math.random() * s) + 1);
        }
 

tonyp

Member
Licensed User
Longtime User
Division by zero gives no error.

Division by zero gives "Infinity", but no errors.

Since there is no error, how do I test for infinity so I can report an ERROR?

(And I consider it more appropriate that division by zero gives an error, as Infinity is more like an answer for LIMITS, e.g., division by a value as it approaches zero.)

TIA

To test:
B4X:
Dim e As Evaluator
Dim ans As Double
e.Initialize
e.SetGlobal("x",0)
ans = e.Evaluate("1/x")
Log("Error Message: " & e.Error)
Log("Error Flag   : " & e.ErrorFlag)
Log("Answer       : " & ans)
 

agraham

Expert
Licensed User
Longtime User
This is what Java does for floating point division. It does not throw exceptions or errors. The behaviour of Basic4android code is the same. You can test against the string "Infinity"
B4X:
Log(ans = "Infinity")
The other possibilities are "-Infinity" and "NaN".

•1/0 yields Infinity.
•(-1)/0 yields -Infinity.
•0/0 yields NaN.

Java would throw exceptions if this were done for integer values but interestingly Basic4android doesn't as it seem to promote some or all integer operations to floating point. I have queried this with Erel.
 

tonyp

Member
Licensed User
Longtime User
OK, it works. Thanks.

I realized I can also compare to 1/0
B4X:
if ans = 1/0 then ...

or, all possibilities:

B4X:
if (ans = 1/0) or (ans = (-1)/0) or (ans = 0/0) then ... error

I suppose this comparison could also be done inside the library and an error set, accordingly.
(Unless you can think of a reason why this would not be required at all times.)
 
Last edited:

JLS

Member
Licensed User
Longtime User
Hello everybody.

I have detected that sometimes the answer it's a little bit unaccurate. For example:

e.Evaluate("3*3") returns 9 (it´s OK)
e.Evaluate("0.03*3) returns 0.09 (it's OK)
e.Evaluate("0.03*3) returns 0.8999999999999 (????)

Can somebody tell me why this happens and how to fix?

Thanks a lot
 

JLS

Member
Licensed User
Longtime User
Thank you very much, Erel. I'm following this way and now it Works fine.

It's hard at the beginning.

Thanks again.
 

Fusseldieb

Active Member
Licensed User
Longtime User
I have a little problem with your library. The variable "I" returns everytime a diferent value.

Example, I resolve the 3x3 matrix:

First, I set the variables:
B4X:
Eval.SetGlobal("A",1)
Eval.SetGlobal("B",1)
Eval.SetGlobal("C",1)
Eval.SetGlobal("D",1)
Eval.SetGlobal("E",1)
Eval.SetGlobal("F",1)
Eval.SetGlobal("G",1)
Eval.SetGlobal("H",1)
Eval.SetGlobal("I",1)

A B C
D E F
G H I

Then, the value goes to:
1 1 1
1 1 1
1 1 3

And everytime I call variable "I", the value increases +1...

I don't know why...

(Other variables doesn't make that mess)

Could you please verify your library for any possible errors? :D

EDIT: Sorry, the fail was on my side. Nevermind :p
(Btw, your library is awesome)

For those who want to know too: I have declared variable "I" later in the code too
B4X:
For i=0 To.....
And THAT make the mess :p
 
Last edited:

imbault

Well-Known Member
Licensed User
Longtime User
I've been meaning to do this for my own use for a while and I have finally got a round tuit that allowed me to get on with it. Everyone should have a round tuit - they are so useful! :)

This is the recursive descent parser from my BasicLib library stripped down to deal with arithmetic functions only. Pass it a valid arithmetic expression as a string and it will return the result. Use a help viewer to see what is supported but basically it will evaluate any arithmetic expression that Basic4android can. It also supports variables that may be used to pass values and store intermediate results.


EDIT :- Version 1.1 has improved error reporting. See post #3 for details.

Hi Agraham, is it possible to add IIF(,,), in your library, I'm OK to pay for this functionality, just tell me, if it's possible and then how much

My best regards

Patrick
 

imbault

Well-Known Member
Licensed User
Longtime User
@agraham , another option, if you please, is to share source code of your library, in order to add other functions

Anyway, thanks for this library

Patrick
 

MaFu

Well-Known Member
Licensed User
Longtime User
@agraham , another option, if you please, is to share source code of your library, in order to add other functions

Anyway, thanks for this library

Patrick
Have a look on the math parser of my MFLib. With this you can create user defined functions.
Example:
B4X:
...
    MF_MathParser.CreateUserFunction("test", 2, "TestEvent"))
    MF_MathParser.Parse("test(5,7)"))
...

Sub TestEvent_Calc(name As String, values() As Double) As Double
    Dim result As Double = 0.0
    For Each v In values
        result = result + v
    Next
    Return result
End Sub
 

MaFu

Well-Known Member
Licensed User
Longtime User
Top