DDMathParser icon indicating copy to clipboard operation
DDMathParser copied to clipboard

How to add a √ (nthroot) operator?

Open horaceho opened this issue 12 years ago • 7 comments

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?

horaceho avatar Jan 31 '13 08:01 horaceho

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.

davedelong avatar Feb 02 '13 16:02 davedelong

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.

davedelong avatar Feb 02 '13 16:02 davedelong

"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))].

horaceho avatar Feb 04 '13 04:02 horaceho

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"];

KamranKhan-DL avatar Sep 03 '13 11:09 KamranKhan-DL

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"];

KamranKhan-DL avatar Sep 04 '13 07:09 KamranKhan-DL

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.

davedelong avatar Jan 04 '14 23:01 davedelong

for square root, I just simple replace √( with sqrt( and it is a walk around to the problem...

j259liu avatar Sep 06 '15 20:09 j259liu