Добавление функции nCr в DDMathParser (с переменными параметрами)

Я изо всех сил пытаюсь добавить новую функцию (nCr) в DDMathParser. Я пытался следовать этим инструкциям автора DDMathParser:

/questions/45228257/mozhet-kto-nibud-ukazat-na-uchebnik-po-dobavleniyu-novyih-funktsij-v-ddmathparser/45228269#45228269

Моя проблема: мне не удается объединить DDExpressions в сложное выражение с переменными...

Можете ли вы помочь мне добавить функцию nCr ( http://en.wikipedia.org/wiki/Binomial_coefficient)

Спасибо!

1 ответ

Автор DDMathParser здесь.

Основная сигнатура для всех функций такова:

DDExpression* ^(NSArray *arguments, NSDictionary *variables, DDMathEvaluator *evaluator, NSError **error);

Поэтому вам нужно создать один из этих блоков, который реализует алгоритм nCr. Есть несколько способов сделать это:

  1. Вы можете реализовать функцию в точности так, как показано в статье, вычисляя факториалы, делая вычитание и делая деление.
  2. Вы можете полностью реализовать функцию в терминах существующих функций факториала, вычитания и деления.
  3. Вы могли бы сделать комбинацию из двух.

Лично я бы порекомендовал последний, потому что он избавляет от необходимости переоценивать аргументы, но также означает, что вам не нужно писать большую часть логики самостоятельно.

Это было бы что-то вроде этого:

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.

Другие вопросы по тегам