Math Parser for Objective C, iOS and OSX

bcParserObjC Math Parser class library implemented in Objective C provides capability to parse and evaluate math formulas given as strings at runtime. bcParserObjC library uses foundation framework. It can be used for iPhone and Mac OSX applications. You may download an evaluation version archive here. The trial version comes with a sample OSX command line program that you can try to understand the capabilities.

MathParser Objective C class supports variables and functions in the expression. You can pre-set values for the variables, or you can register a callback (VariableDelegate protocol) to provide values for variables at runtime. You can also register user defined functions by implementing Function protocol.

Typical code to use the parser is as follows:

   #import "MathParser.h"
   ...
   MathParser *parser = [[MathParser alloc] init];
   parser.expression = @"X+Y";
   [parser setVariable:@"X" withNewValue:5];
   [parser setVariable:@"Y" withNewValue:10];
   double result = parser.value; // parses and evaluates the expression

If the expression cannot be parsed at the time you parse and request the result, a ParserException will be thrown.

  • Easy to use, simple Objective C class API.
  • Functions with 0 or more known number of parameters in the form of: f(x,y,z)
  • Functions with unknown number of parameters, e.g. SUM(a,b,c,…)
  • Comes with predefined math functions.
  • Function protocol to implement user defined functions.
  • VariableDelegate protocol to provide values for undefined variables.
  • Function/variable names start with letters and can contain letters, numbers and underscore (_).
  • Arithmetic Operators: +, -, /, *, ^(power), %(mod)
  • Boolean Operators: <, >, =, &, |, ! ,<>, >=, <=
  • Optimization: Constant expression elimination for repeated tasks.
  • Paranthesis: ( )
  • Provides localization support which is a NSDictionary of message-keys to messages you can set.
  • Optional locale specific decimal separator support (European comma vs US dot)
  • Royalty free distribution.
  • Comes as source code.

MathParser documentation can be found here.

Here is a more complete example:

//  This is a sample program that demonstrates basic usage of
//  bcParserObjC MathParser library.
//

#import <Foundation/Foundation.h>
#import "MathParser.h"

// A VariableDelegate resolves unknown variables:
// (Useful in cases when problem domain is so wide, pre-defining every variable
// is not feasible)
@interface MyVariableDelegate : NSObject
@end
@implementation MyVariableDelegate
-(double) getVariableValue:(NSString *)varName
{
    if ([varName isEqualToString:@"A"]) {
        // If it is a variable that we recognize:
        return 5.0;
    }
    @throw [[NSException alloc] initWithName:@"UnknownVariableException"
            reason:[NSString stringWithFormat:@"Variable '%@' is not defined.", varName]
                    userInfo:nil];
}
@end

// To be used for user defined function example below:
static int factorial(int x)
{
    if (x == 1) {
        return 1;
    }
    if ( x <= 1 ) {
         @throw [[NSException alloc] initWithName:@"FactorialException"
                reason:@"FACT function requires the parameter to be &gt;0" userInfo:nil];
    }
    return x * factorial(x-1);
}

// A user defined function example:
// (User defined functions implement Function protocol)
@interface MyFactorial : NSObject
@end
@implementation MyFactorial
-(double) run:(NSArray *)parameters
{
    if ([parameters count] != 1) {
        @throw [[NSException alloc] initWithName:@"FactorialException"
              reason:@"FACT function requires one integer parameter" userInfo:nil];
    }
    return factorial(floor([parameters[0] getValue]));
}
-(int) getNumberOfParameters
{
    return 1; // This user defined function takes 1 parameter. For example: FACT(5)
}
@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"Testing MathParser");

        MathParser *parser = [[MathParser alloc] init];
        parser.expression = @"x+y/5";
        [parser setVariable:@"X" withNewValue:5];
        [parser setVariable:@"Y" withNewValue:10];
        NSString *output;

        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        parser.expression = @"x-sin(y)";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        parser.expression = @" x * sum( 1,2, 3) ";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        parser.optimizationOn = YES;
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        parser.expression = @" x * max( 1,2, y,3 ) ";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        @try {
            // Invalid expression throws exception:
            parser.expression = @"x+";
            output = [NSString stringWithFormat:@"%f", [parser evaluate]];
            NSLog(@"%@", output);
        }
        @catch (NSException *e) {
            NSLog(@"Expected: %@", [e reason]);
        }

        parser.expression = @" (x / 3.4e-02) + y+x";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        NSArray *vars = [parser getVariablesUsed];
        for (NSString * varName in vars) {
            NSLog(@"   Variable: %@", varName);
        }

        parser.variableDelegate = [[MyVariableDelegate alloc] init];
        // Using variable A whose value will be returned by variable delegate:
        parser.expression = @"X+10/A";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        // Using a user defined function requires one time registration of
        // the function implementation with the parser instance:
        [parser createFunc:@"FACT" withImpl:[[MyFactorial alloc] init] ];
        parser.expression = @"5+FACT(5)";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        NSLog(@" Functions:");
        NSArray *funcs = [parser getFunctions];
        for (NSString * funcName in funcs) {
            NSLog(@"  %@", funcName);
        }

        NSLog(@" Variables:");
        vars = [parser getVariables];
        for (NSString * varName in vars) {
            NSLog(@"   defined: %@", varName);
        }

        // Test locale specific decimals:
        parser.localeSpecificDecimals = YES;
        parser.locale = [NSLocale localeWithLocaleIdentifier:@"de_DE"];
        parser.expression = @" x * sum( 1,1: 2,2: 3,3) ";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        parser.localeSpecificDecimals = NO;
        parser.expression = @" x * sum( 1.1, 2.2, 3.3) ";
        output = [NSString stringWithFormat:@"%f", [parser evaluate]];
        NSLog(@"%@", output);

        // For repeated evaluation of the same expression, parse once before the loop:
        parser.expression = @"X+SIN(Y)/COS(X)";
        [parser parse]; // parse before the loop.
        NSDate *date = [NSDate date];
        for (int i = 0; i < 1000000; i++) {
            [parser setVariable:@"X" withNewValue:5+i];
            [parser setVariable:@"Y" withNewValue:10+i];
            [parser evaluate];
        }
        double timePassed_ms = [date timeIntervalSinceNow] * -1000.0;
        NSLog(@"Milliseconds for 1 million evaluations: %f", timePassed_ms);
    }
    return 0;
}

bcParserObjC License

Licensing is per developer. Once you purchase the component, you can ship the binaries royalty free with your applications. The source code is provided so that you can change to fit your needs. MathParser software license can be viewed here.

Purchasing Math Parser Library for Objective C, iOS, OSX

You can pay with credit card and download bcParserObjC immediately from our online store for only $29.95. The download includes Objective C source code. Upgrades are free for registered users. Licensing is per developer. You can deploy the the component royalty free with your applications as many times as you want. Site license allows any number of developers use the component at your development site. Site License is $290.95. Site licenses can be purchased here.