DDMathParser
DDMathParser copied to clipboard
How to add a √ (nthroot) operator?
What's the proper way to add the √ (nthroot) operator? such that:
3√8
will work as:
nthroot(8,3)
Is there an existing operator which I can use as a reference implementation?
This is slightly complicated. The way things are right now, when the parser encounters a binary operator, it takes the left expression as the first argument and the right expression as the second argument. Thus, 3√8
would become nthroot(3, 8)
. I suppose I could put in a flag on the operator definition to flip the arguments around...
I'll think about this. I agree it's a good suggestion, but it'll require some work to do.
The other thing to consider is that √64
is usually interpreted to mean "the square root of 64". So would 3√64
be "the cube root of 64" or "3 times the square root of 64"? I'm inclined to think it'd be the latter.
"3 times the square root of 64" is a result of Implicit Multiplication. Is possible to let binary operator to have higher precedence over implicit multiplication? And √
only works a unary operator when its left expression is not a number [while (6÷2)√8
is hopefully still nthroot(8,(6÷2))
].
This is for Sqrt - Nthroot can be added in similar way
Step 1
In file _DDOperatorInfo.m under function
- (NSArray *)_buildOperators { add following code
..................... API Code ..................... precedence++; [operators addObject:[self infoForOperatorFunction:DDOperatorPower token:@"**" arity:DDOperatorArityBinary precedence:precedence associativity:DDOperatorAssociativityRight]];
Add Code Here -->
precedence++; //sqrt [operators addObject:[self infoForOperatorFunction:DDOperatorSqrt token:@"√" arity:DDOperatorArityUnary precedence:precedence associativity:DDOperatorAssociativityRight]];
Step 2
- Now go to DDParserTypes.h and add following line of code
extern NSString *const DDOperatorSqrt;
- Then in DDParserTypes.m add following code
NSString *const DDOperatorSqrt = @"Sqrt";
Step 3 (Finally)
Add the following code to your project (preferably in viewDidLoad method of your first view controller) before using the √ operator
DDMathFunction sqrtFunction = ^ DDExpression* (NSArray _args, NSDictionary *variables, DDMathEvaluator *evaluator, NSError *_error) { if ([args count] != 1) //Check for argument count { //fill in *error and return nil *error = [NSError errorWithDomain:@"Arguments not equal to 1" code:10123 userInfo:nil];
NSLog(@"%@", args);
return nil;
}
NSNumber * n = [[args objectAtIndex:0] evaluateWithSubstitutions:variables evaluator:evaluator error:error];
RETURN_IF_NIL(n);
NSNumber *result = [NSNumber numberWithDouble:sqrt([n doubleValue])];
return [DDExpression numberExpressionWithNumber:result];
};
[[DDMathEvaluator sharedMathEvaluator] registerFunction:sqrtFunction forName:@"Sqrt"];
For NthRoot
Step 1
In file _DDOperatorInfo.m under function
precedence++;
[operators addObject:[self infoForOperatorFunction:DDOperatorPower token:@"**" arity:DDOperatorArityBinary precedence:precedence associativity:DDOperatorAssociativityRight]];
precedence++;
//xsqrty
[operators addObject:[self infoForOperatorFunction:DDOperatorXSQY token:@"√" arity:DDOperatorArityBinary precedence:precedence associativity:DDOperatorAssociativityLeft]];
Step 2 (Follow like the above)
Step 3
DDMathFunction function = ^ DDExpression* (NSArray _args, NSDictionary *variables, DDMathEvaluator *evaluator, NSError *_error) { if ([args count] != 2) { //fill in *error and return nil *error = [NSError errorWithDomain:@"Arguments not equal to 2" code:10122 userInfo:nil];
NSLog(@"%@", args);
return nil;
}
NSNumber * firstValue = [[args objectAtIndex:0] evaluateWithSubstitutions:variables evaluator:evaluator error:error];
RETURN_IF_NIL(firstValue);
NSNumber * secondValue = [[args objectAtIndex:1] evaluateWithSubstitutions:variables evaluator:evaluator error:error];
RETURN_IF_NIL(secondValue);
NSString *evalStr = [NSString stringWithFormat:@"nthroot(%@, %@)", secondValue, firstValue];
NSNumber *result = [[DDMathEvaluator sharedMathEvaluator] evaluateString:evalStr withSubstitutions:nil];
return [DDExpression numberExpressionWithNumber:result];
};
[[DDMathEvaluator sharedMathEvaluator] registerFunction:function forName:@"XSQY"];
I just added API to define your own operators, so for now (at least) it's possible to add this yourself (check out the Wiki for details). I'm looking at what it would take to build this in, so I will leave this issue open.
for square root, I just simple replace √( with sqrt( and it is a walk around to the problem...