Следующий код исправляет вашу реализацию C mex.
Проблема, конечно, не в рекурсии...
В вашем коде вместо значений используются указатели (в C важно использовать указатели только в нужных местах).
Вы можете использовать встроенную функцию Matlab: nchoosek
См.: http://www.mathworks.com/help/matlab/ref/nchoosek.html
Работает следующий код:
//choose.c
#include "mex.h"
double choose(double n, double k)
{
if (k==0)
{
return 1;
}
else
{
return (n * choose(n - 1, k - 1)) / k;
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *n, *k, *nk;
int mrows, ncols;
plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
/* Assign pointers to each input and output. */
n = mxGetPr(prhs[0]);
k = mxGetPr(prhs[1]);
nk = mxGetPr(plhs[0]);
/* Call the recursive function. */
//nk=choose(n,k);
*nk = choose(*n, *k);
}
Скомпилируйте его в Matlab: mex choose.c
Выполнить:
choose(10,5)
ans =
252
Это не неэффективная реализация...
Я помогаю исправить вашу реализацию, чтобы использовать ее как "неэффективный пример".
Измерьте выполнение реализации rahnema1:
tic;n = 1000000;k = 500000;nk = prod((k+1:n) .* prod((1:n-k).^ (-1/(n-k))) );toc
Прошедшее время составляет 0,022855 секунды.
Измерьте выполнение реализации Choose.mexw64:
tic;n = 1000000;k = 500000;nk = Choose(1000000, 500000);toc
Истекшее время составляет 0,007952 секунды.
(заняло немного меньше времени, чем prod((k+1:n).* prod((1:n-k).^ (-1/(n-k))))).
Измерение рекурсии Matlab, получение ошибки (даже для n=700 и k=500):
ic;n = 700;k = 500;nk = RecursiveFunctionTest(n, k);toc
Достигнут максимальный предел рекурсии 500 . Используйте set(0,'RecursionLimit',N), чтобы изменить ограничение. Имейте в виду, что превышение доступного пространства стека может привести к сбою MATLAB и/или вашего компьютера.
tic;n = 700;k = 400;nk = RecursiveFunctionTest(n, k);toc
Истекшее время составляет 0,005635 секунды. Очень неэффективно...
Измерение встроенной функции Matlab nchoosek:
tic;nchoosek(1000000, 500000);toc
Внимание: результат может быть неточным. Коэффициент больше 9,007199e+15 и точен только до 15 цифр. В nchoosek на 92 Прошедшее время составляет 0,005081 секунды.
Вывод:
Вам нужно реализовать mex-файл C без использования рекурсии и принять меры.
Измерить без рекурсии:
static double factorial(double number)
{
int x;
double fac = 1;
if (number == 0)
{
return 1.0;
}
for (x = 2; x <= (int)number; x++)
{
fac = fac * x;
}
return fac;
}
double choose(double n, double k)
{
if (k == 0)
{
return 1.0;
}
else
{
//n!/((n–k)! k!)
return factorial(n)/(factorial(n-k)*factorial(k));
}
}
tic;choose(1000000, 500000);toc
Прошедшее время составляет 0,003079 секунды.
Быстрее...
person
Rotem
schedule
24.08.2016
matlabFunction()
, но, как говорят остальные, не используйте здесь рекурсию. - person Ander Biguri   schedule 24.08.2016