The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: RuiLoureiro on December 11, 2010, 06:58:37 PM

Title: Solving expressions
Post by: RuiLoureiro on December 11, 2010, 06:58:37 PM
I want to write a set of procedures to solve
any integer expression with Sub (-), Add (+),
Mul (*), Div (/) or Remainder (\).

Any integer from -4 294 967 295 to 4 294 967 295

The procedures must be as simple as possible
and it must solve any expressions like:

    a)  12 - 3*5 +23 + 5 / 2                                 (=22)
   
    b) (-2 + (-2 * ( 12 - 3*5)+23) + 5) - 15                 (=17)

    c) (-10 - (-2 * ( 12 - 3*5 +23 + 5 / 2) + 20) + 5) - 15   (=4)
    ...

Do you have any ideas ? Tell me

To start i need to solve expressions like a)
and then like b) or c)
Title: Re: Solving expressions
Post by: fearless on December 11, 2010, 07:58:28 PM
http://en.wikipedia.org/wiki/Shunting_yard_algorithm and http://en.wikipedia.org/wiki/Reverse_Polish_notation are probably worth looking at in relation to this.
Title: Re: Solving expressions
Post by: jj2007 on December 11, 2010, 08:02:13 PM
There are several threads dealing with this, e.g. Simple formula parser (http://www.masm32.com/board/index.php?topic=4230.msg31714#msg31714) and Floating point Math (http://www.masm32.com/board/index.php?topic=11226.msg83039#msg83039).

Unfortunately it is not trivial - the macros that solve the formulas below are easy to use (Let MyRes=68.16122-G2*(f1+3*1.8**2.2)+G2*f1) but have about 400 lines. And I never finished it because it was buggy :toothy

G1=12.34, G2=43.21 (both global REAL10)
f1=11.11, f2=22.22 (both local REAL10)

Calculating 68.16122-G2*(f1+3*1.8**2.2)+G2*f1 :
Expected value is       -404.2335
Calculated value is     -404.2335
-- Second operand is smaller

Calculating 4-G1*(f2-3.4)+G2*f1 :
Expected value is       251.8243
Calculated value is     251.8243
** Operands are equal or almost equal at 8 digits precision

Calculating 4-G2*(f1+34+3)+G2*f1+2000 :
Expected value is       405.23
Calculated value is     405.23
** Operands are equal or almost equal at 8 digits precision

Calculating 4+5-G2*(f1+34*3)+G2*f1+2000 :
Expected value is       -2398.42
Calculated value is     -2398.42
** Operands are equal or almost equal at 8 digits precision

Calculating 4+5-G2*(f1+(34/3))+G2*f1+2000 :
Expected value is       1519.287
Calculated value is     1519.287
** Operands are equal or almost equal at 8 digits precision

Calculating 4+5-G2*(f1+34*3)-G2*f1+2000 :
Expected value is       -3358.546
Calculated value is     -3358.546
** Operands are equal or almost equal at 8 digits precision
Title: Re: Solving expressions
Post by: dedndave on December 11, 2010, 08:34:07 PM
Quote-4 294 967 295 to 4 294 967 295

33 bits ?
will get you: -4 294 967 296 to 4 294 967 295

i will add this link to the pile   :P

http://en.wikipedia.org/wiki/Order_of_operations
Title: Re: Solving expressions
Post by: RuiLoureiro on December 11, 2010, 09:13:19 PM
fearless,
            shunting-yard algorithm is a method for parsing ...
           
            it seems to be complex.
            I think i dont need to do it and i can solve the problem
            i think we can use a table to solve it and it is more simple
jj,
            Thanks but i want only 32 bit integers
            Simple formula parser is complex

dave,
            33 bits ? why ? 32 bits: sign plus 0 to FFFFFFFFh
            so
            Any integer from -4 294 967 295 to 4 294 967 295

    To solve this:
            b) (-2 + (-2 * ( 12 - 3*5)+23) + 5) - 15

           we need to solve 1-   12 - 3*5   =X
                                    2-   -2*X+23    =Y
                                   3-   -2 + Y + 5 =Z
                                   4-    Z - 15    = result     no ?

            so we need to parse 12 - 3 * 5 and solve and then ...
            its a linear method no ?
Title: Re: Solving expressions
Post by: qWord on December 11, 2010, 09:46:03 PM
Quote from: jj2007 on December 11, 2010, 08:02:13 PMAnd I never finished it because it was buggy
are you interested in further developing? - I've some macros (non- recursively,masm & jwasm) , that are ready to use ...  however, the documentation is currently very bad.

qWord
Title: Re: Solving expressions
Post by: oex on December 11, 2010, 11:45:11 PM
32 bits has 4,294,967,296 range total not -4,294,967,296 to 4,294,967,296.... 256*256*256*256.... The 33rd bit would be the sign for this range
Title: Re: Solving expressions
Post by: dedndave on December 11, 2010, 11:45:42 PM
i think Hutch mentioned this in another thread...
one problem is - the minus sign is both an operator and a modifier
it takes a little logic to sort it out

Rui,
for 33 bits, the signed range is -4 294 967 296 to +4 294 967 295
Title: Re: Solving expressions
Post by: MichaelW on December 12, 2010, 06:35:27 AM
Rui,

Will the expressions be created at runtime from user inputs, or is this something that could be done with the preprocessor? The MASM preprocessor can solve your example expressions, but you must use MOD instead of "\" and the results will be limited to 32 bits.

Title: Re: Solving expressions
Post by: jj2007 on December 12, 2010, 07:24:45 AM
Quote from: qWord on December 11, 2010, 09:46:03 PM
Quote from: jj2007 on December 11, 2010, 08:02:13 PMAnd I never finished it because it was buggy
are you interested in further developing? - I've some macros (non- recursively,masm & jwasm) , that are ready to use ...  however, the documentation is currently very bad.

qWord

Hi qWord,

Thanks for the generous offer (not your first one - check MasmBasic.inc, cStyle$ macro :wink).
I've put this a bit on ice, partly because of lack of time, partly because I had some higher priorities for MasmBasic (http://www.masm32.com/board/index.php?topic=12460), and partly because it is so bloody complex to get something like Let MyResult=68.92972-GlobTb2*(LocFlt1+3*1.8**2.2)+GlobTb1*LocFlt2+1276 to work properly - you certainly know the problem.
The ambition here is that Let should behave as if it was BASIC. And indeed the statement above works:
GlobTb1=12.34, GlobTb2=43.21 (both global REAL10)
LocFlt1=11.11, LocFlt2=22.22 (both local REAL10)

Calculating 68.92972-GlobTb2*(LocFlt1+3*1.8**2.2)+GlobTb1*LocFlt2+1276 :
Expected value is       666.6667
Calculated value is     666.6667
** Operands are equal or almost equal at 8 digits precision


... but I haven't included it in MasmBasic simply because there are only slightly different cases where it misbehaves, and that is not acceptable for a Basic dialect. A second problem is that the simple Let above disassembles to over 80 lines of mostly FPU instructions - and there might be a way to do it with less.

Maybe we could PM each other to exchange ideas and sources?
Title: Re: Solving expressions
Post by: tenkey on December 12, 2010, 09:11:25 AM
I normally use recursive descent method to roll my own parser. But that uses recursive procedure calls.

The operator precedence method doesn't use recursion, but it does require one or two explicit stacks (not the automatic stack used by ESP). It is fundamentally the "railyard shunt" algorithm. The brackets require special precedence rules unless you use "double precedence", where there is a "left side precedence" and a "right side precedence".

The minus sign vs. subtraction operator is solved by allowing the negation operator, and always treating "-" as an operator. You determine the difference between negation and subtraction by noting if the "-" was at the beginning, or if the symbol to the left of the "-" was an operator or a value. (A left bracket is an "operator", a right bracket is the end of a value.)

Title: Re: Solving expressions
Post by: jj2007 on December 12, 2010, 09:42:42 AM
just for fun... sequences like fld st(1) ... fst st(1) show that there is a lot of room for improvement; the macro has currently 400 lines, though.

CPU Disasm for Let MyRes=68.92972-GlobTb2*(LocFlt1+3*1.8**2.2)+GlobTb1*LocFlt2+1276
fst st(2)
ffree st
fincstp
fld tbyte ptr [GlobTb2] ; float 43.210000000000000850
fst st(3)
ffree st
fincstp
fld tbyte ptr [ebp-38]
fst st(4)
ffree st
fincstp
push 3
fild dword ptr [esp]
pop eax
fst st(5)
ffree st
fincstp
push 12
fild dword ptr [esp]
pop eax
push 0A
fidiv dword ptr [esp]
pop eax
fst st(6)
ffree st
fincstp
push 16
fild dword ptr [esp]
pop eax
push 0A
fidiv dword ptr [esp]
pop eax
fld st(6)
call X2Exp
fst st(6)
ffree st
fincstp
fld st(5)
fmul st, st(5)
fst st(5)
ffree st
fincstp
fld st(4)
fadd st, st(4)
fst st(4)
ffree st
fincstp
fld st(3)
fmul st, st(3)
fst st(3)
ffree st
fincstp
fld st(2)
fsubr st, st(2)
fst st(2)
ffree st
fincstp
fld tbyte ptr [GlobTb1]          ; float 12.339999999999999860
fst st(3)
ffree st
fincstp
fld tbyte ptr [ebp-2C]
fmul st, st(3)
fst st(3)
ffree st
fincstp
fld st(2)
fadd st, st(2)
fst st(2)
ffree st
fincstp
push 4FC
fild dword ptr [esp]
pop eax
fadd st, st(2)
fst st(2)
ffree st
fincstp
fld st(1)
fst st(1)
ffree st   ; float 666.66670278498440780
fincstp
wait
fstsw ax
Title: Re: Solving expressions
Post by: RuiLoureiro on December 12, 2010, 03:36:32 PM
        Thanks all
Dave,
        «for 33 bits, the signed range is -4 294 967 296 to +4 294 967 295»

        i want 32 bits dword plus sign + or -
        If you type - 4 294 967 295:   sign = - and value=0FFFFFFFFh
       
MichaelW,
        «Will the expressions be created at runtime from user inputs...»

        YES
;***---
        My first try is Calcula12. It uses my own linear method
         
        Try it. Is there a bug ? Tell me please
         
        It seems to work, but it is under test
Title: Re: Solving expressions
Post by: dedndave on December 12, 2010, 03:43:52 PM
hi Rui,

not for 33-bit two's compliment ;)

1FFFFFFFFh is -1
10000000h is -4294967296
Title: Re: Solving expressions
Post by: qWord on December 12, 2010, 09:24:21 PM
Quote from: jj2007 on December 12, 2010, 07:24:45 AMMaybe we could PM each other to exchange ideas and sources?
:thumbu, check your PMs
Title: Re: Solving expressions
Post by: jj2007 on December 12, 2010, 10:24:45 PM
Quote from: qWord on December 12, 2010, 09:24:21 PM
Quote from: jj2007 on December 12, 2010, 07:24:45 AMMaybe we could PM each other to exchange ideas and sources?
:thumbu, check your PMs

Thanks, impressive :U
Title: Re: Solving expressions
Post by: qWord on December 12, 2010, 10:36:26 PM
Quote from: jj2007 on December 12, 2010, 10:24:45 PM
Thanks, impressive :U
thx  :bg
however, it is not 100% finish (but usable).

BTW: REAL10-var's also work after calling
fSlvSetGlbPrecision <REAL10>
or using the macro fSlv10
Title: Re: Solving expressions
Post by: RuiLoureiro on December 13, 2010, 04:21:36 PM
Hi Dave,
      I dont want to work in twos's complement but in sign-amplitude
      we need two variables (not only one): _Sign and _Value
      _Value can be any 32 bit value
      With two's complement we use only 31 bits for value and 1 bit for signal
      and we need only one variable, but i dont want this.

      Did you try Calcula12 ? Does it work as expected ?

      This is my procedure to solve any expression without ():

Quote
ResolveIt       proc

                mov     esi, offset _TblOperation
                xor     ebx, ebx

    _loop1:     mov     edi, offset _TblOperand
                mov     edx, dword ptr [esi + ebx*4]
                cmp     edx, 3          ; 1=Sub(-) 2=Add(+) 3=Mul(*) 4=Div(/) 5=Rem(\)
                jb      short _next1
                ;
                push    ebx
                    shl     ebx, 4
                    invoke  OperationAB,[edi + ebx + $SIGN1$], [edi + ebx + $OPR1$],
                                        [edi + ebx + $SIGN2$], [edi + ebx + $OPR2$], edx
                pop     ebx
                jc      _end

                mov     dword ptr [esi + ebx*4], 0

                call    SaveAntRes
                call    SaveNxtRes
                jnc     short _next1
                ;
                cmp     _NoAnt, 0
                je      _Ok                 ; END
                ;
    _next1:     add     ebx, 1
                cmp     ebx, dword ptr [esi - 4]
                jb      short _loop1

    ;---***---***---***---
     
                xor     ebx, ebx

    _loop2:     mov     edi, offset _TblOperand
                mov     edx, dword ptr [esi + ebx*4]
                cmp     edx, 0
                je      short _next2
                ;
                push    ebx
                    shl     ebx, 4
                    invoke  OperationAB,[edi + ebx + $SIGN1$], [edi + ebx + $OPR1$],
                                        [edi + ebx + $SIGN2$], [edi + ebx + $OPR2$], edx                   
                pop     ebx
                jc      _end
               
                call    SaveNxtRes
                jnc     short _next2
                ;
                ; END
                ; »»»
    _Ok:        invoke  ToRclCnv, SignW, OperandW, addr ResultZ
                clc
                ret
                ;
    _next2:     add     ebx, 1
                cmp     ebx, dword ptr [esi - 4]
                jb      short _loop2
                ; »»»»»»»»»»»»»»»»»»
                ; It cannot end here
                ; »»»»»»»»»»»»»»»»»»
                call    SetError2
                stc   
    _end:       ret
ResolveIt       endp
Title: Re: Solving expressions
Post by: qWord on December 13, 2010, 05:31:47 PM
hi RuiLoureiro,

maybe an bug or simply an limit?:
(1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)=ERROR

qWord
Title: Re: Solving expressions
Post by: RuiLoureiro on December 13, 2010, 05:52:30 PM
Quote from: qWord on December 13, 2010, 05:31:47 PM
hi RuiLoureiro,

maybe an bug or simply an limit?:
(1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)=ERROR
qWord
Hi qWord,
                   First, thank you
                   It is a limit of 20 operations if im correct
                   But i can change the table to operate with 500 or 1000... operations
                   The tables are defined to use only 20 operations

                       dd 20
                       dd 0                        <-- current number of operations
_TblOperation   dd 20 dup (?)


now works till 200 operations inside brackets


EDIT:
To solve this:          -2 + (-2* (12 - 3*5) + 23 ) + 5

the 1ª expression is:   -2+(-2*(12-3*5)+23)+5   
and we calculate:               12-3*5         (= @ )              @=-3

now, the expression is: -2+(-2*@+23)+5   
and we calculate:           -2*@+23            (= @ )              @=29

now, the expression is: -2+@+5
at last the result is:   32

When we try to find an operand or an operator we need to test to find @
When we solve an expression with () we replace it with @
This is my linear method  :green2
Title: Re: Solving expressions
Post by: RuiLoureiro on December 14, 2010, 07:30:29 PM
Till now anything OK

the method used:
         
                    1- Read expression to _BufferX
                    2- Copy _BufferX to _BufferY and remove spaces and get
                       the buffer length Y
                       If we find @ than ERROR (this is used inside to replace...)
                       
                    3- Scan _BufferY from right to left to find an expression
                       inside brackets - try to find first ")" and than "("
                       If not, exit to 6
                    4- Copy the expression to a WorkBuffer and than call
                       the procedure SolveExpress
                    5- Save the result on _BufferAT (from top to bottom)
                       Replace the expression by @
                       Start again until we have not brackets
                    6- Call SolveExpress to solve the last expression in _BufferY

                    SolveExpress: build 2 tables: operations and operands
                                  whenever we find @, from bottom to top,
                                  get the values from _BufferAT;
                                  If it is a constant, convert it
                                  When we have the tables, call ResolveIt
                                   
                    Note that the expression is solved from left to right
                         while we scan _BufferY from right to left;
                         We move values to _BufferAT from top to bottom
                         and retrieve from bottom to top.

If _BufferY="-(5-3)+2*((5-3)+2*(3-5))"

1º expression:  -(5-3)+2*((5-3)+2*@)                _BufferAT = -2;

2º expression:  -(5-3)+2*(@+2*@)                    _BufferAT = -2;+2

3º expression:  -(5-3)+2*@                          _BufferAT = -2;

4º expression:  +@+2*@                              _BufferAT = -2; -2
                   
last solution:   -6

                    What do you think about ?
                    Is there anything wrong ? Tell me
Title: Re: Solving expressions
Post by: RuiLoureiro on December 15, 2010, 04:18:23 PM
Hi

Quote
The first procedure to solve an expression is this:

If _BufferY is defined like

                dd 120
                dd 0            <--- number of characters
_BufferY    db 121 dup (0)

invoke  LookExpress, addr _BufferY  to solve the expression in _BufferY

Quote
;   _TblOperandAt is an array of 2 dwords to save sign
;                 and result of each operation  (each @)
;
LookExpress     proc    pRcl:DWORD

                mov     edx, offset _TblOperandAt
                mov     dword ptr [edx - 4], 0
                ;
    _start:     mov     esi, pRcl
                mov     ecx, dword ptr [esi - 4]
                ;
                cmp     ecx, 0
                jne     short _loop1
                ;
    error1:     call    SetError
                stc
                ret
               
    _loop1:     sub     ecx, 1
                movzx   eax, byte ptr [esi + ecx]
                cmp     al, ')'
                je      short _found1
                ;
                cmp     ecx, 0
                jne     short _loop1
                ;
                ; not found -> solve the last expression
                ; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»

                invoke      SolveExpress, esi
                ret           
;---
    _found1:    cmp     ecx, 0
                je      short error1
                ;
                mov     _OffsetLst, ecx
;---
    _loop2:     sub     ecx, 1
                movzx   eax, byte ptr [esi + ecx]
                cmp     al, '('
                je      short _found2
               
                cmp     al, ')'
                je      short _found1
               
                cmp     ecx, 0
                jne     short _loop2
                je      error1
;---
    _found2:    mov     _OffsetFst, ecx

                mov     ebx, _OffsetLst
                sub     ebx, ecx
                sub     ebx, 1
               
                cmp     ebx, 0
                je      short _rem
                ;
                cmp     ebx, 1
                ja      short _found3
                ;
                ; Constant
                ;
                mov     ebx, _OffsetFst
                add     ebx, 1
                movzx   eax, byte ptr [esi + ebx]

                cmp     al, '@'
                je      short _rem
               
                cmp     al, '0'
                jb      error1
               
                cmp     al, '9'
                ja      error1
                ;
                ; Remove ()
                ; »»»»»»»»»
      _rem:     mov     ebx, _OffsetFst
                mov     byte ptr [esi + ebx], 20h
                mov     ebx, _OffsetLst
                mov     byte ptr [esi + ebx], 20h
                invoke  RemSpaces, esi
                jmp     _start
;---------------------------------------
    _found3:    mov     edi, offset WrkBuffer

                push    esi
               
                add     esi, _OffsetFst
                add     esi, 1

                mov     dword ptr [edi - 4], ebx
                mov     byte ptr [edi + ebx], 0
               
        @@:     sub     ebx, 1               
                movzx   eax, byte ptr [esi + ebx]
                mov     byte ptr [edi + ebx], al
                jnz     short @B

                pop     esi

                ; »»»»»»»»»»»»»»»»»»»»»»»»»»»
                ;     Wrk is constant ?
                ; »»»»»»»»»»»»»»»»»»»»»»»»»»»
                invoke  VrfOperand, edi, [edi - 4]
                jnc     _rem                            ; yes
               
                cmp     eax, 1
                je      error1
                ;
                ; Operation
                ; »»»»»»»»»
                invoke  SolveExpress, edi
                jc      error1
                ; »»»»»»»»»»»»»»»»»»»»»»
                ;  Replace (...) by AT
                ; »»»»»»»»»»»»»»»»»»»»»»
                invoke  RemExpress, esi

                call    AdjustSign

                call    SaveAt

                jmp     _start
LookExpress     endp
Title: Re: Solving expressions
Post by: RuiLoureiro on December 15, 2010, 06:50:44 PM
Try Calcula14 and see all expressions one by one
Title: Re: Solving expressions
Post by: RuiLoureiro on December 16, 2010, 07:03:13 PM
Now, Calcula15 solve expressions like 2^5+2^4+2^3+2^2+2^1+2^0 
     or 2^3+2*(5-3)+10
Title: Re: Solving expressions
Post by: RuiLoureiro on December 17, 2010, 09:06:49 PM
The last Calcula15 has a bug:   2^3-2^3 = 16  !!!

Now, Calcula15 solve expressions like:  2^5+2^4+2^3+2^2+2^1+2^0 
     or 2^3+2*(5-3)+10      or (((2^3)))+1   or  -(-2^3+1)-5    -2^3+2^3 ...

It is under test. Did you find another bug ?

Title: Re: Solving expressions
Post by: RuiLoureiro on December 18, 2010, 07:32:02 PM
The last Calcula15 has a bug: a procedure VrfOperand  proc pRcl:DWORD, Len:DWORD
                              exits with  ret  4  instead of   ret 8

Calcula16   does  (1-2*3)^3   but not  (2^3)^3 (the base cannot be an exponential)
            and   (-5)^3   or (-5)^2    -5^3   (the exponent should be 0 to +31 )
           
            it does any integer expression with
            Sub (-), Add (+), Mul (*), Div (/), Remainder (\), Exp(^)
            i hope !       

New Calcula16 because  ---3^3 doesnt give error
Title: Re: Solving expressions
Post by: RuiLoureiro on December 19, 2010, 05:41:15 PM
I am working now in Calcula16...meanwhile

I decided to show all Calcula14 project (it doesnt make exponentials)
Calcula14.zip   is = .asm.inc, .glb  & .exe
You can assemble it: Use Console Assemble & Link
Express your opinion or comments if you want
Title: Re: Solving expressions
Post by: RuiLoureiro on December 20, 2010, 06:20:58 PM
the linear method used in Calcula16:
         
                    1- Read expression to _BufferX
                   
                    2- Copy _BufferX to _BufferY and remove spaces and get
                       the buffer length Y

                       Remove some types of expressions (to have less problems after):
                       this (x+y..z)      is =   x+y...z
                       this (((x+y)))+z   is =   (x+y)+z

                       Test some types of errors (to have less problems after)
                       ... +-(x+y)        is  ERROR
                       ... -+-x+y         is  ERROR

                       Now, START

invoke LookExponent:
                    3- Scan _BufferY from right to left to find the operator ^
                       If not, exit to 5

                    4- For each operator ^, find exponent and base ( base^exponent )

                       If base is an expression, copy it to BufferB
                       and  «invoke LookExpress, addr BufferB» to get the base
                       
                       Save the result on _TableEX (from top to bottom) and replace
                       the expression "base^exponent" by #
                       Go on (goto 3)

invoke LookExpress:                       
                    5- Scan _BufferY from right to left to find an expression
                       inside brackets - try to find first ")" and than "("
                       If not, exit to 8
                       
                    6- Copy the expression to a WorkBuffer and than call
                       the procedure SolveExpress
                       
                    7- Save the result on _TableAT (from top to bottom)
                       Replace the expression by @
                       Start again until we have not brackets (goto 5)
                       
                    8- Call SolveExpress to solve the last expression in _BufferY

                    9- The result: the value is in OperandW and sign in SignW

                   10- Convert it to string _ResultZ

                   11- Show string _ResultZ
                   
                    SolveExpress: build 2 tables: operations and operands
                                  whenever we find @, from bottom to top,
                                  get the values from _TableAT;
                                  whenever we find #, from bottom to top,
                                  get the values from _TableEX;

                                  If it is a constant, convert it
                                  When we have the tables, call ResolveIt

                    ResolveIt gives the result in OperandW and SignW
                   
                    We can exit from a procedure with 3 types of results:
                                  a)    correct     (exit clc)
                                  b)    error       (exit stc EAX=0)
                                  c)    overflow    (exit stc EAX=1)
                                   
                    Note that each expression is solved by SolveExpress
                         from left to right
                         while we scan _BufferY from right to left;
                         
                         We move values to _TableAT or _TableEX from
                         top to bottom and retrieve them from bottom to top.
                         
                         _TableAt and _TableEx work like a stack: when we
                         scan we PUSH; when we want the values, we POP

    Anyone has any other idea to add.
    Do you want help us
    EDIT:
            The procedures doesnt solve expressions with exponentials or powers inside
            brackets. The result cannot be correct
Title: Re: Solving expressions
Post by: oex on December 21, 2010, 10:45:11 AM
This link might be of use to you

http://www.php.net/manual/en/language.operators.precedence.php
Title: Re: Solving expressions
Post by: RuiLoureiro on December 21, 2010, 04:42:26 PM
Thanks oex,
            That link say nothing to me

Calcula16 has a problem of brackets precedence
If the expression has not brackets, the result is correct
One simple example is this: 2^4 + (2*2^3) + 2^2 = 36 (Calcula16 gives 44)
I am working on Calcula16 to solve this problem
Title: Re: Solving expressions
Post by: oex on December 21, 2010, 04:56:08 PM
The link was for future reference as you develop the algorithm.... That PHP expression table has many other operator types that you dont have yet....

With regard to your current problem everything in brackets should be calculated first bottom level up returning

2^4+16+2^2

I have downloaded your code but not had a chance to look at it properly yet

That example doesnt require bracket precidence though I think suggesting it is a different issue.... 2*2^3 is already calculated before additions

Do you mean? 2^4 * (2+2^3) + 2^2 = 36 (Calcula16 gives 44)

At least that's the only way I can make 44.... If so you are simply not calculating bracketed expressions first.... Find the lowest level brackets and work up ie

2*(2+2*(2+2)) ->

Loop to find first bracket ( then mark position.... Repeat this task until you reach ) then resolve marked position to ) giving

2*(2+2*4)

Repeat until no brackets
Title: Re: Solving expressions
Post by: RuiLoureiro on December 21, 2010, 05:55:42 PM
Quote
With regard to your current problem everything in brackets should be
calculated first bottom level up returning

        This is exactly what i do

Quote
Do you mean? 2^4 * (2+2^3) + 2^2 = 36 (Calcula16 gives 44)

        No.   Not 2+  but 2*: This: 2^4 + (2*2^3) + 2^2 = 36 (Calcula16 gives 44)
        (I know very well why calcula16 gives 44)

        Calcula16 solve this correctly: 2^4 + (2+2^3) + 2^2 = 16+(2+8)+ 4 =16+2+8+4=30

        Why ? Simply because this 2^4 + (2+2^3) + 2^2 = 2^4 + 2+2^3 + 2^2. This is:
        we can remove brackets
       
Quote
...If so you are simply not calculating bracketed expressions first

       Yes. Expressions that involve powers (or exponentials) inside brackets.
       If we have not powers inside brackets we have not problems

Ok, thanks oex
Title: Re: Solving expressions
Post by: oex on December 21, 2010, 06:01:05 PM
OK you told me this: 2^4 + (2*2^3) + 2^2 = 36 (Calcula16 gives 44) -> Without brackets this = 36
So I assumed you meant this: 2^4 * (2+2^3) + 2^2 = 36 (Calcula16 gives 44)    -> Without brackets this = 44

I cant see how you get 44 otherwise :lol But only just loaded the code.... My assumption is that if the former function is correct then you aren't calculating powers with precidence over both * and + but I will check

The PHP site table also shows operator precedence
Title: Re: Solving expressions
Post by: RuiLoureiro on December 21, 2010, 07:22:14 PM
Quote
OK you told me this: 2^4 + (2*2^3) + 2^2 = 36 (Calcula16 gives 44)
-> Without brackets this = 36
            Calcula16 gives a wrong result
            With or Without brackets this = 36 too
            Without brackets we solve powers first, than * or / ... +,-
           
Calcula16 does this:  2^3 + 2 * 2^4 + 2^2 = 8 + 2 * 16 + 4 = 12 + 32 = 44
It changes 2^3 with 2^4 because it gets 2^4 first when try to solve (2*2^3) - gets 2^4 instead -
and than 2^3 and than 2^2 !

Quote
I cant see how you get 44 otherwise 
            Now you know how to get 44  :lol
    EDIT:
    If we remove brackets and want to solve 2^4 + 2*2^3 + 2^2, calcula16 gives 36
    (correct)
Title: Re: Solving expressions
Post by: RuiLoureiro on December 22, 2010, 05:07:30 PM
Hi all

Calcula17 is only one step more to solve the problem
I dont know if the problem is completely solved or not

Meanwhile, now, it solves correctly the expressions like

2^4 + (2*2^3) + 2^2 = 36        - powers inside brackets
and
(1-2*3)^2+(5-2*3)+2^2+1=29      - note that the base can be an expression:(1-2*3)^2
                                                    but cannot have exponentials inside
                                                    exponent must be 0 to 31

It must solve all other cases (i hope)

    EDIT:
            One little problem when base=1  (-1)^4=-1 (error)
            or exponent = 0                 (-1)^0=-1 (error)
           
            NEW calcula17: now (-1)^4 = 1 and (-1)^0= 1

Title: Re: Solving expressions
Post by: RuiLoureiro on December 23, 2010, 03:02:50 PM
The LookPower algorithm
-----------------------------------
The LookPower algorithm is used with expressions without brackets

Let the expression be pointed by ESI and the length is ECX
Let _ResultZ the string where we put the final result (the ascii code)
Let SignZ the sign of the result and OperandZ the value of the result
SignZ and OperandZ are 2 dwords
Let _TblPower an array of 400 dwords (for 200 results)

a) From right to left scan the expression to find ^ operator
   This is done from ecx-1 to ecx=0

    _loop:      sub     ecx, 1
                cmp     byte ptr [esi + ecx],'^'
                je      short _found1
                ;
                cmp     ecx, 0
                jne     short _loop
                ;
                ; not found / done
                ; »»»»»»»»»»»»»»»»
                clc
                exit
                ;         
    _found1:    cmp     ecx, 0
                je      short goto error
                ;
                ; found -> try to find Base and Exponent
                ; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
                If error goto error; If overflow goto overflow

                Calculate Power=Base^Exponent   (do not destroy ESI or ECX)
                If overflow goto overflow
                (the result is in SignZ and OperandZ )
               
                Save the result (in _TblPower)  (do not destroy ESI or ECX)
                Replace expresssion by #        (do not destroy ESI or ECX)
                jump to _loop

b) For each Power, save the result in an array _TblPower (from top to bottom)
    and replace the power expression by #

c) When ecx=0 than exit with clc

    When error or overflow than exit with stc
    If error set the string "ERROR" to _ResultZ
    If overflow set the string "OVERFLOW" to _ResultZ

;---***
Example:  expression = "4+5^3+2+5^2+2*3-5^1"

          the final expression is this:
          (note that when the sing is "-" we put this sign in SignZ)
         
          expression = "4+#+2+#+2*3+#" where _TblPower is this:

                                dd 3        <--- number of values in the table
                    _TblPower   dd 1       
                                dd 5
                                ;
                                dd 0        <--- sign 0= +    1= -1
                                dd 25
                                ;
                                dd 0
                                dd 125

    When we call SolveExpress to solve this last expression because
    SolveExpress solves it from left to right, the first # at the left
    is in the last in the _TblPower ... and the last in the first in _TblPower.
   
    When SolveExpress finds the first # it replaces it by (0,125) and
    _TblPower is now equal to this
     
                                dd 2 <--- number of values in the table
                    _TblPower   dd 1       
                                dd 5
                                ;
                                dd 0        <--- sign 0= +    1= -1
                                dd 25
                                ;
                                dd 0
                                dd 125

    When SolveExpress finds the second # it replaces it by (0,25) and
    _TblPower is now equal to this
     
                                dd 1 <--- number of values in the table
                    _TblPower   dd 1       
                                dd 5
                                ;
                                dd 0        <--- sign 0= +    1= -1
                                dd 25
                                ;
                                dd 0
                                dd 125

    When SolveExpress finds the third # it replaces it by (1,5) and
    _TblPower is now equal to this
     
                                dd 0 <--- number of values in the table
                    _TblPower   dd 1       
                                dd 5
                                ;
                                dd 0        <--- sign 0= +    1= -1
                                dd 25
                                ;
                                dd 0
                                dd 125

    If it tries to find onother #, there is an error because the
    number of values in the table is 0

    After we invoke LookPower, we invoke SolveExpress and SolveExpress
    solves the expression = "4+#+2+#+2*3+#" and replaces it by @ in
    the original expression 

    Note that LookPower is called inside LookExpress whenever it
    finds an expression with brackets.
Title: Re: Solving expressions
Post by: RuiLoureiro on December 26, 2010, 12:21:02 PM
The LookPower algorithm (with some details)
-------------------------------------------

    _start:     sub     ecx, 1
                cmp     byte ptr [esi + ecx],'^'
                je      short _found1
                ;
    _loop:      cmp     ecx, 0
                jne     short _start
                ;
                ; not found / done
                ; »»»»»»»»»»»»»»»»
                clc
                exit
                ;         
    _found1:    cmp     ecx, 0
                je      short error
                ;
                ; found -> try to find Base and Exponent
                ; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
                If error goto error; If overflow goto overflow

                Call    Exponent    (do not destroy ESI or ECX)
                Call    GetBase     (define the leftmost ECX)
               
                Calculate Power=Base^Exponent   (do not destroy ESI or ECX)
                If overflow goto overflow
                (the result is in SignZ and OperandZ )
               
                Save the result (in _TblPower)  (do not destroy ESI or ECX)
                Replace expresssion by #        (do not destroy ESI or ECX)
                ;
                jump to _loop       ; goto test ECX
Title: Re: Solving expressions
Post by: RuiLoureiro on December 27, 2010, 07:07:15 PM
Hi
    My algorithm seems to be finished.
    Now, Calcula18 solves expressions like

                 2*3+(7-2*3+2^3-2^2)^3-10 (the base is an expression with powers)
Title: Re: Solving expressions
Post by: RuiLoureiro on December 29, 2010, 05:19:00 PM
The algorithm to calculate an expression with Sub(-), Add(+), Mul (*), Div(/),
Remainder(\) and Powers (^) is finished.

I decided to show all Calcula19 project

Calcula19.zip   is = .asm.inc, .glb  & .exe
You can assemble it: Use Console Assemble & Link

Express your opinion or comments if you want
or tell me bugs if exist
Title: Re: Solving expressions
Post by: Farabi on December 30, 2010, 01:02:06 AM
Impresive RuiLoureiro  :U
Title: Re: Solving expressions
Post by: TmX on December 30, 2010, 03:46:57 AM
Hi RuiLoureiro,

I found a simple bug:
QuoteType an expression and press enter [ ex: -2 + 3*(7 - 2*8) + 3^3 ]
2^(3-3)
This is your expression: 2^(3-3)
This is your expression: 2^(3-3)
This is your Result:  ERROR
2^(3-3)=ERROR

It should be 1, right?
Title: Re: Solving expressions
Post by: dedndave on December 30, 2010, 03:52:59 AM
20 = 1

but, how do you evaluate 00 ?   :P
Title: Re: Solving expressions
Post by: oex on December 30, 2010, 03:55:58 AM
Quote from: dedndave on December 30, 2010, 03:52:59 AM
20 = 1

but, how do you evaluate 00 ?   :P

.if Pow=0
mov eax, 1
.endif
Title: Re: Solving expressions
Post by: dedndave on December 30, 2010, 04:15:25 AM
many mathematicians would not agree
some say 0, some say 1, and i think most say it is undefined
Title: Re: Solving expressions
Post by: TmX on December 30, 2010, 04:30:16 AM
Quote from: dedndave on December 30, 2010, 04:15:25 AM
many mathematicians would not agree
some say 0, some say 1, and i think most say it is undefined

0/0=0, because 0 = 0 x 0 ... (1)
0/0=1, because 0 = 0 x 1 ... (2)

by (1) and (2), we can conclude that 1 = 0  :dazzled:
Title: Re: Solving expressions
Post by: Farabi on December 30, 2010, 04:34:28 AM
Also, 2^1.5 mean (2*1)*(2*0.5) in case you did not know.

4^4.5 = (4^4)*(4*0.5)
Title: Re: Solving expressions
Post by: oex on December 30, 2010, 11:49:02 AM
If M$ Calculator says 0^0=1 who am I to disagree ^ ^ :lol
Title: Re: Solving expressions
Post by: dedndave on December 30, 2010, 12:05:29 PM
oh - and....
0/0 and 1/0 are not 0   :bg
they are both undefined
although, i've had calculus instructors try to tell me they were infinity - lol
Title: Re: Solving expressions
Post by: RuiLoureiro on December 30, 2010, 12:43:58 PM
TmX,
    «I found a simple bug»

    Its not a bug: The exponent must be a positive constant from 0 to 31
                   NOT an expression

dedndave,
          My Calcula19 gives 0^0=0 ( in higher math it is undefined )
          but (expression)^0 = 1   if expression is not 0
         
oex,
          «If M$ Calculator says 0^0=1 who am I to disagree»

          I disagree, if the base tends to 0 first it is 0 not 1
          Calcula19 must give a result and gives 0
         
Farabi,
          «Also, 2^1.5 mean (2*1)*(2*0.5) in case you did not know»

          My Calcula19 gives ERROR because exponent must be from 0 to 31

          Calcula19 works with any integer from -4 294 967 295 to 4 294 967 295
          so the result must be any integer from -4 294 967 295 to 4 294 967 295
          but the exponent must be from 0 to 31
           
        Thanks all
Title: Re: Solving expressions
Post by: dedndave on December 30, 2010, 01:09:00 PM
Quotededndave,
          My Calcula19 gives 0^0=0 ( in higher math it is undefined )

i have taken too many courses in "higher math" - lol
what i am saying is, this is still a subject of discussion and disagreement amongst "higher" mathematicians

a realistic approach is to apply the right rule for the job, after evaluating with 0, 1, and undefined
usually, if this result pops out it means.....

(http://img251.imageshack.us/img251/1359/usererror.jpg)
Title: Re: Solving expressions
Post by: Farabi on December 30, 2010, 01:30:22 PM
Quote from: oex on December 30, 2010, 11:49:02 AM
If M$ Calculator says 0^0=1 who am I to disagree ^ ^ :lol

Well I guess it is better than giving a crash "Division by zero" error message.
Title: Re: Solving expressions
Post by: Farabi on December 30, 2010, 01:37:18 PM
Quote from: dedndave on December 30, 2010, 01:09:00 PM
Quotededndave,
          My Calcula19 gives 0^0=0 ( in higher math it is undefined )

i have taken too many courses in "higher math" - lol
what i am saying is, this is still a subject of discussion and disagreement amongst "higher" mathematicians

a realistic approach is to apply the right rule for the job, after evaluating with 0, 1, and undefined
usually, if this result pops out it means.....

(http://img251.imageshack.us/img251/1359/usererror.jpg)

Download the latest patch, it fixed, look

(http://ompldr.org/vNnM5NA/Error.bmp)

:green
Title: Re: Solving expressions
Post by: dedndave on December 30, 2010, 01:44:09 PM
 :lol

you guys can do math, too !!!
Title: Re: Solving expressions
Post by: oex on December 30, 2010, 02:13:59 PM
The assumption that has to be made is not whether 0^0=0 or 0^0=1 (as both are wrong).... The question is, with the avoidance of an error which will produce the best result in a greater equation....

If 0 then further
% = Divide By Zero Error
/ = Divide By Zero Error
* = 0
+ = Right Answer
- = Right Answer

If 1 then further
% = Right Answer
/ = Right Answer
* = Right Answer
+ = Answer + 1
- = Answer - 1

Either way a further answer is wrong :lol the difference is whether your answer is a maximum of 1 out or result out/errors I think :lol

0^0=1 is Error Handling (As it handles crash errors at the risk of minimal data loss)
0^0=0 is lazy Error Handling (As it favours one crash error over the next crash error)
Title: Re: Solving expressions
Post by: RuiLoureiro on December 30, 2010, 02:14:42 PM
dednadve
        i have taken too many courses in "higher math" - lol

        Yes i do

        EDIT:
                another solution is: 0^0= ERROR
                If you prefer edit .asm change it to exit with ERROR
Title: Re: Solving expressions
Post by: oex on December 30, 2010, 05:42:56 PM
:lol Yep.... Contextualising is the best policy....

http://www.wired.com/science/discoveries/news/1998/07/13987

0/0=?
?*0=0
(0 = -Infinity - 0 - +Infinity

0/0*1=0
0/0*2=0
(1=2)

X^0=1
(Why except 0?)

http://www.google.co.uk/#hl=en&expIds=17259,28041&xhr=t&q=0%5E0&cp=3&pf=p&sclient=psy&rlz=1W1RNTN_en&aq=0&aqi=&aql=&oq=0%5E0&gs_rfai=&pbx=1&fp=42df9320e81e9757

So much for logic :lol
Title: Re: Solving expressions
Post by: RuiLoureiro on December 30, 2010, 05:57:24 PM
oex,
        contextualizing ? what do you mean ? 
Title: Re: Solving expressions
Post by: oex on December 30, 2010, 06:01:10 PM
Quote from: RuiLoureiro on December 30, 2010, 05:57:24 PM
oex,
        contextualizing ? what do you mean ? 

Deriving a result based on result you need ie if your program will crash if you supply 0 or return error and it will sink the ship like here then return 1 even though it's wrong :lol
http://www.wired.com/science/discoveries/news/1998/07/13987
Title: Re: Solving expressions
Post by: RuiLoureiro on December 30, 2010, 06:07:17 PM
Quote from: oex on December 30, 2010, 06:01:10 PM
Deriving a result based on result you need ie if your program will crash if you supply 0 or return error and it will sink the ship like here then return 1 even though it's wrong :lol
http://www.wired.com/science/discoveries/news/1998/07/13987
                 too much logic... under logic  :wink

X^0=1                   0^X=0
(Why except 0?)         (Why except 0?)
Title: Re: Solving expressions
Post by: Farabi on December 31, 2010, 02:36:40 PM
anyone tried this

mov eax,some_value
xor ecx,ecx
div ecx


I dunno if Im making mistake, but it create a fault on the processor. Anyone experiencing that? I did.
Title: Re: Solving expressions
Post by: RuiLoureiro on December 31, 2010, 02:47:42 PM
Quote from: Farabi on December 31, 2010, 02:36:40 PM
anyone tried this

mov eax,some_value
xor ecx,ecx
div ecx


I dunno if Im making mistake, but it create a fault on the processor. Anyone experiencing that? I did.

          No, but i think it gives a fault
Title: Re: Solving expressions
Post by: dedndave on December 31, 2010, 02:48:09 PM
divide by zero is the highest priority condition that x86 CPU's trap   :P
that's why it generates INT0
Title: Re: Solving expressions
Post by: oex on December 31, 2010, 02:59:20 PM
Quote from: RuiLoureiro on December 30, 2010, 06:07:17 PM
X^0=1                   0^X=0
(Why except 0?)         (Why except 0?)

:lol Because you cant divide by 0.... There are other arguements.... Looks like this one was Euler's....

http://www.faqs.org/faqs/sci-math-faq/specialnumbers/0to0/
http://en.wikipedia.org/wiki/Division_by_zero
Title: Re: Solving expressions
Post by: RuiLoureiro on December 31, 2010, 03:25:19 PM
:lol Because you cant divide by 0.... There are other arguements.... Looks like this one was Euler's....
Quote
oex,
         For me y^x is an indeterminate form when y=0 and x=0.
         For me 0^0 is not 1. I dont follow your point of view.
         If for convenience you want it 1, yes you can why not ?
         Play with 0^0+0^0+0^0+0^0+0^0=5 why not ?
Title: Re: Solving expressions
Post by: oex on December 31, 2010, 03:35:23 PM
:lol This is OK I dont believe I've ever typed 0^0 before now I was just trying to show you/others the other points, mathmatic and programatic, logical and illogical.... My own expression evaluator uses 0^0=1 but there is no 'right' result, following your posts I may well update this to better error check different scenarios ie 1+0^0=1 but 10*0^0=10.... Currently however my code calculates:

0^0+0^0+0^0+0^0+0^0=5 yes

However in a more usual situation
10*0^0=10 and 0^0 is 'ignored'

This is more important for my expression evaluator as it also does more complex functionality however it really does depend on context what is the right result....
Title: Re: Solving expressions
Post by: RuiLoureiro on December 31, 2010, 06:23:01 PM
i typed 0^0 in all my calculators and they all give ERROR
They dont want to say nothing about it
I play with 1^1+1^1+1^1+1^1+1^1=5

Have a nice new year