|
-
Nov 2nd, 2002, 05:00 PM
#1
Thread Starter
New Member
String Formula to Integer
Hello, does anyone have information or a link to a place where I can learn how to take an entire formula written as a string, and convert it into an integer?
For example a function called Convert that takes works something like...
CString formula = "5 + 3*6 - (2+6)^5";
int x = Convert(formula);
And Convert() evaluates the entire string and returns a value.
Any help would be greatly appreciated, thanks.
-
Nov 2nd, 2002, 05:50 PM
#2
1. Look for the operator with the LOWEST precedence in the string, not inside parenthesis (keep a variable with the nesting level, if '(' level++, if ')' level--)
2. Run the Convert function on everything before the operator, and everything after the operator, preform the operation on those two results.
3. If there is no operator found at step 1 you either have a expression in parenthesis, remove the parenthesis, and call Convert on that string.
If there are no parenthesis you have a number (or if you want to extend your parser later on, a named variable) you can convert it to an int (std::stringstream, boost::lexical_cast, atio)
This is not the fastest way to do it, but it is the easiest. (You could also write a function that uses no recursion, and keeps a stack of partialy evaluated values. Such an algorithm will be 10 times as long and complex)
-
Nov 2nd, 2002, 06:05 PM
#3
Thread Starter
New Member
The only problem with such a method would be... what if I have multiple operators? How do I handle it then?
Referring to the example I posted, there are 5 operations being performed, how would I keep track of the algorythm handling the brackets first, then exponentiating the bracket, then multiplying and then adding? What about brackets within brackets and so on...
-
Nov 2nd, 2002, 06:25 PM
#4
The algorithm would work something like:
Code:
Covert("5 + 3*6 - (2+6)^5")
step 1-> the '+' at position 2, split into "5" and "3*6 - (2+6)^5".
a=Convert("5")
returns 5
b=Convert("3*6 - (2+6)^5")
lowest precedence: '-' at position 4
a=Convert(3*6)
lowest precedence: '*' at pos 1
a=Convert("3")
returns 3
b=Convert("6")
returns 6
returns a*b (which is 18)
b=Convert("(2+6)^5)")
lowest precedence: '^' at pos 5
a=Convert("(2+6)")
in parenthesis, remove
returns Convert("2+6")
lowest precedence: '+' at pos 1
a=Convert("2")
returns 2
b=Convert("6")
returns 2
returns a+b (which is 8)
b=Convert(5)
returns 5
returns a^b (which is 32768)
returns a-b (which is -32750)
returns a+b (which is -32745)
The key is that the functions is recursive, it calls itself to calculate sub-expressions
-
Nov 2nd, 2002, 06:37 PM
#5
Thread Starter
New Member
That pseudocode should be very... very helpful.
I'll try and implementing it into my scripting language, thanks a lot.
-
Nov 2nd, 2002, 07:27 PM
#6
Thread Starter
New Member
Well I got to work on it, and it does have one BEDMAS problem.
Since the algorythm splits formulas into 2 sections, and then splits the right section of the formula again into 2 sections, and keeps on repeating until no sections are left, what happens is it messes up subtraction and addition.
For example, a string like "5 - 1 + 5" should work out to 9 using BEDMAS, but what the algorythm seems to be doing is:
Code:
convert(5 - 1 + 5)
split into "5" and "1 + 5"
a = convert("5")
returns 5
b = convert("1 + 5")
split into "1" and "5"
a = convert("1")
returns 1
b = convert("5")
returns 5
returns (a + b) which is 6
returns (a - b) which is -1
-
Nov 2nd, 2002, 09:40 PM
#7
Frenzied Member
Build an expression tree. Leaf nodes contain values, non-leaves contain operators. Use an in-order traversal to evaluate.
Z.
-
Nov 3rd, 2002, 07:42 AM
#8
If you take the last operator with the lowest precedence (+ and - have equal precedence), instead of the first, it should work.
-
Nov 3rd, 2002, 09:39 AM
#9
transcendental analytic
have two stacks, an operand and an operator stack. traverse the string from left to right. push operands on the stack, push operators on the operator stack, when encountering operators with lower precedence, a close parentesis or the end of the string, pop the operator and the amount of operands it requires and push them alltogether onto the operand stack until precedence is equal or higher, respective a start parentesis is found, as well as the start of the string. Ex:
1+2*(3+4)+5
[1][]0
[1][+]1
[1,2][+]1
[1,2][+,*]2
[1,2][+,*,(]0
[1,2,3][+,*,(]0
[1,2,3][+,*,(,+]1
[1,2,3,4][+,*,(,+]1
[1,2,4 3 +][+,*]2 (right parentesis found)
[1,3 4 + 2 *][+]1 (lower precedence)
[3 4 + 2 *1 +][]1 (end of string)
The evaluation can be done at these stages, but if you're writing a script and need variables, using postfix notations reduce the runtime load
3 4 + 2 *1 + is a postfix expression and is evaluated easily using a single operand stack, as precedence and parentesis are irrelevant.
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Nov 4th, 2002, 12:54 PM
#10
But infix is more intuitive for the user.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Nov 4th, 2002, 02:08 PM
#11
Monday Morning Lunatic
Depends. Some people are used to stack-based calculators.
Although they're usually older people though
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Nov 4th, 2002, 03:12 PM
#12
transcendental analytic
I'd say it depends how you're taught, it would be unintuitive but "real" oop would 3+4 be math.aritmethic.plus(math.aritmethic.three,math.aritmethic.four)
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Nov 4th, 2002, 04:59 PM
#13
We're not talking real OOP here, we're talking about practical uses (or did I miss something?)
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Nov 4th, 2002, 08:26 PM
#14
transcendental analytic
I know, but I like to do that sort of comments on OOP anyway 
If people were taught postfix math in school they'd find infix very hard to comprehend, with precedence and parentesis and everything.
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Nov 5th, 2002, 04:33 AM
#15
But infix is the way we talk, and it's not going to change.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|