This function takes an array of strings and numbers and recursively processes it as a kind of "calculating program". The structure is based on Reverse Polish Notation, so the top object in the stack (last in the array) determines what to do with the next one (or two) items in the program. For example, if the array was [1, 2, "+"], the solution would be 3.
In the case of errors, it should return an
NSString
describing the error that happened.If more than one error occurs in processing, it is not clear which error should receive priority, so I've chosen to prioritize the first error found and ignore any further errors.
I think that this code could be made much more simple, but I'm not sure how best to do that in Objective C. What suggestions do you have to improve this code?
+ (id)popOperandOffProgramStack:(NSMutableArray *)stack
{
id result;
double dResult;
id topOfStack = [stack lastObject];
if (topOfStack) [stack removeLastObject];
if ([topOfStack isKindOfClass:[NSNumber class]])
{
result = topOfStack;
}
else if ([topOfStack isKindOfClass:[NSString class]])
{
id rightSide = [self popOperandOffProgramStack:stack];
if (![rightSide isKindOfClass:[NSNumber class]]) {
return rightSide;
}
double r = [(NSNumber *)rightSide doubleValue];
NSString *operation = topOfStack;
if ([[self class] isBinaryOperation:operation]) {
id leftSide = [self popOperandOffProgramStack:stack];
if (![leftSide isKindOfClass:[NSNumber class]]) {
return leftSide;
}
double l = [(NSNumber *)leftSide doubleValue];
if([operation isEqualToString:@"+"]) {
dResult = l + r;
} else if([operation isEqualToString:@"-"]) {
dResult = l - r;
} else if([operation isEqualToString:@"*"]) {
dResult = l * r;
} else if([operation isEqualToString:@"/"]) {
if(r == 0.0) {
return @"Error: Tried to divide by zero";
} else {
dResult = l / r;
}
}
} else if ([operation isEqualToString:@"+/-"]) {
dResult = -r;
} else if([operation isEqualToString:@"sin"]) {
dResult = sin(r);
} else if([operation isEqualToString:@"cos"]) {
dResult = cos(r);
} else if([operation isEqualToString:@"sqrt"]) {
if(r < 0) {
return @"Error: tried to sqrt a negative number";
}
dResult = sqrt(r);
} else if([operation isEqualToString:@"π"]) {
dResult = 3.141592654;
} else {
/* unknown operations and unset variables will return 0 */
dResult = 0.0;
}
result = [NSNumber numberWithDouble:dResult];
}
return result;
}