Добавление функции nCr в DDMathParser (с переменными параметрами)
Я изо всех сил пытаюсь добавить новую функцию (nCr) в DDMathParser. Я пытался следовать этим инструкциям автора DDMathParser:
Моя проблема: мне не удается объединить DDExpressions в сложное выражение с переменными...
Можете ли вы помочь мне добавить функцию nCr ( http://en.wikipedia.org/wiki/Binomial_coefficient)
Спасибо!
1 ответ
Автор DDMathParser здесь.
Основная сигнатура для всех функций такова:
DDExpression* ^(NSArray *arguments, NSDictionary *variables, DDMathEvaluator *evaluator, NSError **error);
Поэтому вам нужно создать один из этих блоков, который реализует алгоритм nCr. Есть несколько способов сделать это:
- Вы можете реализовать функцию в точности так, как показано в статье, вычисляя факториалы, делая вычитание и делая деление.
- Вы можете полностью реализовать функцию в терминах существующих функций факториала, вычитания и деления.
- Вы могли бы сделать комбинацию из двух.
Лично я бы порекомендовал последний, потому что он избавляет от необходимости переоценивать аргументы, но также означает, что вам не нужно писать большую часть логики самостоятельно.
Это было бы что-то вроде этого:
DDMathFunction nCrFunction = ^(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
if ([args count] != 2) {
*error = [NSError errorWithDomain:DDMathParserErrorDomain code:DDErrorCodeInvalidNumberOfArguments userInfo:@{NSLocalizedDescriptionKey : @"nCr requires 2 arguments"}];
return nil;
}
DDExpression *first = [args objectAtIndex:0];
DDExpression *second = [args objectAtIndex:1];
NSNumber *n = [first evaluateWithSubstitutions:vars evaluator:eval error:error];
if (n == nil) { return nil; }
NSNumber *k = [second evaluateWithSubstitutions:vars evaluator:eval error:error];
if (k == nil) { return nil; }
// some validation here to guarantee that 0 ≤ k ≤ n
// now, re-box the numbers in expressions to pass off to other functions
DDExpression *nExpression = [DDExpression numberExpressionWithNumber:n];
DDExpression *kExpression = [DDExpression numberExpressionWithNumber:k];
// build the algorithm
DDExpression *f1 = [DDExpression functionExpressionWithFunction:DDOperatorFactorial arguments:@[kExpression] error:error]; // k!
// the other half of the denominator
DDExpression *subtract = [DDExpression functionExpressionWithFunction:DDOperatorMinus arguments:@[nExpression, kExpression] error:error]; // (n-k)
DDExpression *f2 = [DDExpression functionExpressionWithFunction:DDOperatorFactorial arguments:@[subtract] error:error]; // (n-k)!
// the full denominator
DDExpression *denominator = [DDExpression functionExpressionWithFunction:DDOperatorMultiply arguments:@[f1, f2] error:error]; // k!(n-k)!
// the numerator
DDExpression *numerator = [DDExpression functionExpressionWithFunction:DDOperatorFactorial arguments:@[nExpression] error:error]; // n!
// the whole thing
DDExpression *final = [DDExpression functionExpressionWithFunction:DDOperatorDivide arguments:@[numerator, denominator] error:error]; // n!/(k!(n-k)!)
return final;
};
С помощью этого блока вы можете зарегистрировать функцию на DDMathEvaluator
:
[[DDMathEvaluator sharedMathEvaluator] registerFunction:nCrFunction forName:@"nCr"];
Это оно!
Теперь вы можете сделать:
NSNumber *n = [@"nCr(4, 3)" numberByEvaluatingString];
Предупреждение: код набран в браузере и не скомпилирован. Caveat Implementor
Кстати, если это функция, которую вы хотели бы видеть встроенной в DDMathParser, пожалуйста, откройте новую проблему на Github.