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)
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.
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
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
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 ?
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
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
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
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.
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?
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.)
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
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
hi Rui,
not for 33-bit two's compliment ;)
1FFFFFFFFh is -1
10000000h is -4294967296
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
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
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
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
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
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 bracketsEDIT:
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
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
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
Try Calcula14 and see all expressions one by one
Now, Calcula15 solve expressions like 2^5+2^4+2^3+2^2+2^1+2^0
or 2^3+2*(5-3)+10
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 ?
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
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
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
This link might be of use to you
http://www.php.net/manual/en/language.operators.precedence.php
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
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
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
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
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)
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
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.
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
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)
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
Impresive RuiLoureiro :U
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?
20 = 1
but, how do you evaluate 00 ? :P
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
many mathematicians would not agree
some say 0, some say 1, and i think most say it is undefined
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:
Also, 2^1.5 mean (2*1)*(2*0.5) in case you did not know.
4^4.5 = (4^4)*(4*0.5)
If M$ Calculator says 0^0=1 who am I to disagree ^ ^ :lol
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
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
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)
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.
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
:lol
you guys can do math, too !!!
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)
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
: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
oex,
contextualizing ? what do you mean ?
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
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?)
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.
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
divide by zero is the highest priority condition that x86 CPU's trap :P
that's why it generates INT0
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
: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 ?
: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....
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