Result is not true

Aug 24, 2008 at 10:32 AM
I wrote the code as followings.

    Private Function EvaluateExpression(ByVal Expression As String) As Object
        Dim Result As Object

        Try
            MyExpression = ExpressionFactory.CreateGeneric(Of Double)(Expression, MyContext)

            Result = MyExpression.Evaluate()
        Catch ex As Exception
            Result = ex.Message
        End Try

        Return Result
    End Function

I tried to test this code by entering data but there is a sample return the wrong answer.

I input '4*4/10' the result is '1'. It should be '1.6'. While I input '4.0*4.0/10.0', it return '1.6'. If it is 1.6 the first sample should be 2, right?

Thanks in advance.

Aug 25, 2008 at 8:13 PM
I would think that 1 would be the correct answer for your first example.

INT x INT/INT = INT

   4   x  4  /  10  =  1     <=  the integer portion of 1.6

I could be wrong as I haven't played with this in a long while, but I don't believe Flee would explicitly round if all the values in the expression are integers.  There are a couple of things you can try to determine the framework's behavior.

First, you can try changing one of the numbers to an implicit double by adding '.0' at the end and leaving the other two as integers (i.e. 4*4.0/10). I would think that you would get the double answer of '1.6' under this scenario. This should force a cast to a double value and if not then there is probably a bug in the framework as an INT x DBL / INT = DBL.

Another thing to try is something that lands on the mid point between the integer values, such as 5 x 5 / 10 and see if you get 2 or 3. Again I would assume and integer of 2 as it's the integer portion of 2.5. And try something that lands below the midpoint between the integer values such as (8 x 8 / 10 = 6.4 => 6).

It's been a while since I've looked at this code, but in my implementation of Flee, I force all integer values to doubles during the parse and before the evaluation, but this solution may not be suitable for your needs.

-MindCore
Aug 26, 2008 at 2:51 AM
Thank you MindCore.

I try as you suggest the results are as followings.

5*5/10
2
8*8/10
6
4*4/10
1
4*4.1/100
0.164
4*4.0/10
1.6
5*5/10.0
2.5
8*8/10.0
6.4
You will see that if there is at least a variable to be double, the result will be double. If all numbers are integer, the result will be integer. I think, this is bug because my code is 'MyExpression = ExpressionFactory.CreateGeneric(Of Double)(Expression, MyContext)'. That is all number in the expression should be cast to double although user enter number as integer. If all numbers have to add '.0' for double, it is not practical for programming. What do you think?

Dusit

Aug 27, 2008 at 4:24 AM
Edited Aug 27, 2008 at 4:25 AM
Dusit,

   Unfortunately I don't think it's a bug in Flee, it's just the nature of the beast.  The data type for the generic does not tell the parser that numbers are to be evaluated as doubles.  It tells the ExpressionFactory that anything that's entered into the Expression must be of type double or evaluate to a double.  I believe that the quickest way to solve your problem is to modify Flee to evaluate integers as doubles when parsing.

To confirm this, if you check out the Grammar file you will see the following lines:

// Primitives
INTEGER                 = <<\d+(u|l|ul|lu)?>>
REAL                         = <<\d*\.\d+([e][+-]\d{1,3})?f?>>

Notice that the regular expressions for integer would include patterns such as 4u for an unsigned integer, 4lu or 4ul for long unsigned integer, 4l for long integer and of course 4 for a standard integer. The real pattern includes floats such as 4.0f, doubles such as 4.0, and doubles in scientific notation such as 4e+1 <= note that the sign is required and only up to three digits can follow the sign.

When Grammatica is run against this Grammar file, it creates a few files, but the file with the pattern definitions is ExpressionTokenizer.vb.  One solution is to modify the patterns specified in this file to basically eliminate the integer pattern and then recompile Flee.  Play around with this and let me know if this helps solve your problem.

This hasn't been tested and you will have to change some other code, but you can try these.

INTEGER  = 
<<\d*(i|u|l|ul|lu)+>>       now you must explicitly specify an integer
REAL         =   <<\d*.?\d+([e][+-]?\d+)?f?>>

Good luck
Mindcore
Aug 27, 2008 at 7:02 AM
Thank you Midcore.

I do not see FLEE code, however, I will try to change and re-compile. Maybe, the next version, this point will be solved.

Dusit
Sep 1, 2008 at 1:32 PM
Hi again,

I have some more wrong results. The followings are my code.
Dim MyExpression As Ciloci.Flee.IGenericExpression(Of Double)
Dim MyContext As Ciloci.Flee.ExpressionContext
Dim Variables As Ciloci.Flee.VariableCollection

MyContext = New Ciloci.Flee.ExpressionContext()
MyContext.Imports.AddType(GetType(Math))
Variables = MyContext.Variables

Private Function EvaluateExpression(ByVal Expression As String) As Object
        Dim Result As Object

        Try
            MyExpression = Ciloci.Flee.ExpressionFactory.CreateGeneric(Of Double)(Expression, MyContext)
            Result = MyExpression.Evaluate
        Catch ex As Ciloci.Flee.ExpressionCompileException
            Result = ex.Message
        End Try

        Return Result
End Function
I call EvaluateExpression function for evaluating expression. I enter the previous questions and get the wrong answer. This time I got the wrong answer again. Please the result.
sin(30)
-0.988031624092862
cos(30)
0.154251449887584
sin(90)
0.893996663600558
You will see that the result is not true. Sin(30) should be 0.5 and Sin(90) should be 1. How wrong do I code?

Thanks,
Dusit
Sep 1, 2008 at 2:08 PM
Read the documentation for Math.Sin and Math.Cos (and so on):

http://msdn.microsoft.com/en-us/library/system.math.sin.aspx

a
    Type: System..::.Double

    An angle, measured in radians.

So, use radians, and it will work :)
Coordinator
Nov 9, 2008 at 9:39 PM
MindCore is right.  When an arithmetic operation has two integers, the result is an integer.  If either operand is a double, then the result is a double.  I made it work just like in C#.

However, this issue has come up a couple of times so I might put in a new option to force all numbers to doubles.