We're tackling a pretty tricky problem at work right now. The application we're making allows the user to enter in an equation that we'll calculate for them. For example, let's say that one of these equations is Field2 from the database * 3 / 20. The user can store these equations in a table for use later on. The hard part isn't storing or retrieving or supplying the right values for the variables, it's evaluating the equation. Here are a few reasons why.
First, the equation is stored as text. A * isn't a multiplication sign, it's a '*', just another character. You have to interpret those characters as operators. That is to say, you have to know that a '*' means multiply. Will you support logs, natural logs, trigonometry? Right away, you're limiting what the user can do, because the only allowed operators are the ones you know to parse.
Second, you have to do something with the order of operations. Going back to the equation I listed before, you have to know that Field2 * 3 / 20 can't be calculated in the way we've outputted it. Instead, the calculations have to be done in a certain order according to the order of operations for us to get the right answer. (One of the few mnemonics that's ever stuck with me Please Excuse My Dear Aunt Sally, for the order of operations).
The order of operations is hard. If you don't believe me, try to come up with a rule of thumb for processing an equation like a^b/d*e^f/g*h^i^j. Where do you start there? You have to start at the right place, or else you'll come up with something distinctly wrong. Even if you know the order of operations, does the user entering the equation? It's possible that you can evaluate the equation correctly and deliver the wrong result, if they got their part wrong.
Assuming your language doesn't just have a magical evaluator that can handle these problems for you, you can apply some pretty far-out theories to problems like this. If you dig the formal language thing, you may want to dive into Parsing Expression Grammar and see what you can do. If you're a classicist, maybe Dijikstra's shunting yard algorithm will work (description is about halfway down that page). Don't let fancy terms like 'shunting yard algorithm' dismay you; it's just a way to transform something into Reverse Polish notation.
What do I suggest? Uhhhmm, I don't know yet. I'm going to meditate on it. I'm going to go to my happy place for a while, crunch the options, and see what makes sense. Right now, I'm leaning heavily towards just taping a Mickey Mouse calculator onto the jewel case when the app ships.
Posted by Cody at January 19, 2006 08:19 PM