7

I would like to know how to evaluate a string representation of an equation as if it were a real equation:

if(@"15+14==23")
{
    //True statement...
}
else
{
    //False statement....
}

I want to return "false" because 15+14 does not equal 23. How can I get this to work?

jscs
  • 63,694
  • 13
  • 151
  • 195
  • possible duplicate of [Writing a simple equation parser](http://stackoverflow.com/questions/4582398/writing-a-simple-equation-parser) – rob mayoff Dec 23 '11 at 16:05
  • Are these strings coming from a data source, or user input? You will need to figure out what types of math equation's you want to support and then go from there. (ie what operands, how many operands and if the user will ever type ==) (Do you want support for 1*1*1*1x1*1=1 ?) – Jesse Black Dec 23 '11 at 16:05
  • The string will come from a fixed data source, there are numbers from 0 - 20 , equation ( + - * / ) and equal (==) – Punataro Puhn Chaturaphit Dec 23 '11 at 16:15
  • We are trying to create a scrabble-like math equation game – Punataro Puhn Chaturaphit Dec 23 '11 at 16:16
  • See my answer http://stackoverflow.com/questions/14155360/convert-to-float-and-calculate/14155699#14155699 – TheTiger Jan 05 '13 at 08:00

3 Answers3

7

Here is an example how to do it with NSPredicate:

NSPredicate *p = [NSPredicate predicateWithFormat:@"1+2==3"];
NSLog(@"%d", [p evaluateWithObject:nil]);
p = [NSPredicate predicateWithFormat:@"1+2==4"];
NSLog(@"%d", [p evaluateWithObject:nil]);

The first NSLog produces 1 because 1+2==3 is true; the second produces 0.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @Mithras: in the same spirit you could say Apple is being too nice to lazy programmers by providing objective c instead of assembly. Lazy programmers write code that is less functional/more buggy, not less code – Daniel Dec 23 '11 at 16:11
  • @Mithras I don't think it's a case of "being nice": parsers are hard to get right, even by "hard-working" programmers using the right tools. Apple's offering a simple, easy to learn, solution for everyone helps the world by not breeding poorly-written parsers :) – Sergey Kalinichenko Dec 23 '11 at 16:12
  • @Dani It sounds to me like you don't want to learn and grow. This is typical of people who aren't too serious about programming. –  Dec 23 '11 at 16:29
  • @dasblinkenlight It's not that hard to write a basic mathematical expression parser, and making the effort improves one's understanding and appreciation of computer science. –  Dec 23 '11 at 16:32
  • 2
    @Mithras Although it's not hard to write a parser, it's best to do it as an exercise while you're still in a high school or at a university. I wrote more than a dozen parsers myself, and my first three or four were throw-away code by most practical standards. My point is that learning exercises and production code are best kept separate. – Sergey Kalinichenko Dec 23 '11 at 16:54
  • @Mithras it may not be hard to write a basic parser, but as soon as you want to write one that correctly handles operator associativity, exponentiation, and negation, things get *really* complicated. Even `NSPredicate` gets some things wrong. – Dave DeLong Dec 23 '11 at 17:01
  • @Mithras: I wrote enough parsers to learn and grow over that subject. However, I will not use a manuall one when NSPredicate is available, just like you won't write your own formatted printing function when printf is available. – Daniel Dec 24 '11 at 07:33
  • @PunataroPuhnChaturaphit What about it? It is a valid predicate, it is just not obvious what it does. – Sergey Kalinichenko Dec 26 '11 at 11:27
  • @PunataroPuhnChaturaphit It does not look like the parser of the `predicateWithFormat:` method is smart enough to parse conditions on booleans: it fails to parse `(1<2)==(3<4)` as well. It handles integers OK, though. – Sergey Kalinichenko Dec 26 '11 at 12:20
  • Using `NSExpression` for this seems to be closer to the problem. http://stackoverflow.com/questions/16785873/how-to-evaluate-the-string-equation-in-ios/16785975#16785975 – Amin Negm-Awad Jul 02 '16 at 13:12
3

So, this is a problem that I believe is a lot more complicated than the linked question lets on (although the question is asking for a "simple" equation parser).

Fortunately for you, I think this is a really interesting problem and have already written one for you: DDMathParser.

It has a good amount of documentation, including things like how to add it to your project and a high overview of its capabilities. It supports all of the standard mathematical operators, including logical and comparison operators (||, &&, ==, !=, <=, etc).

In your case, you'd do something like this:

NSNumber *result = [@"15+14 == 23" numberByEvaluatingString];
if ([result boolValue] == YES) {
  ....True statement....
} else {
  .....False statement.....
}

As a heads up, DDMathParser is made available under the MIT license, which requires you to include the copyright information and the full text of the license in anything that uses it.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • I'd bet you will never see your copyright notice in anyone's software on iTunes. The same type of laziness that causes a person to not want to learn how to write an expression evaluator will also incline them to basically steal from you. You would help society more by providing tutorials rather than completed code. –  Dec 23 '11 at 16:37
  • @Mithras actually, I know of several people who use it and are properly following the license. And it's not "laziness" that dissuades people from writing an expression evaluator; it's that it's a *really hard problem* if you want it to be universally correct. By your argument, Apple should just provide tutorials on how to implement touch handling, the responder chain, rotation detection, etc, instead of just giving us the UIKit framework. Yeah, not going to happen. – Dave DeLong Dec 23 '11 at 16:59
0
NSString *equation = @"15+14==29";


NSPredicate *pred = [NSPredicate predicateWithFormat:equation];

NSExpression *LeftExp = [pred leftExpression];

NSExpression *RightExp = [pred rightExpression];    


NSNumber *left = [LeftExp expressionValueWithObject:nil context:nil];

NSNumber *right = [RightExp expressionValueWithObject:nil context:nil];


if ([left isEqualToNumber:right]) {
    NSLog(@"yes left is equal to right");
}
else{
    NSLog(@"yes left is NOT equal to right");

}

NSLog(@"left %@", left); 

NSLog(@"right %@", right);