3
$\begingroup$

I want to write recursive function for calculating the arithmetic mean of a vector.

For $X(n)=\{1,2,3,\ldots, n\}$, the formula is ${\rm Mean}(X(n))=((n-1)\, {\rm Mean}((X(n-1))+X_n)/n$.

My program works in my R-language version, but here in Mathematica it takes in account only the last two number. How can I fix my code?

Meen[x_] := (
   If[Length[x] == 1, 
     Return[x],
     n = Length[x] - 1; 
     y = x[[1 ;; n]]; 
     result = 1/(n + 1)*(n*Meen[x[[1 ;; n]]]  + x[[n + 1]])]
   )

X = {1, 2, 3, 4, 5};
Meen[X]
{9/5}
$\endgroup$

4 Answers 4

5
$\begingroup$

Here is another way to do it. It is a tail-recursive formulation, so you don't have to worry about exceeding $RecursionLimit.

mean[{}, k___, m_: 0] := m
mean[{most___, last_}, k_: 0, m_: 0] := mean[{most}, k + 1, (k m + last)/(k + 1)]

Test:

SeedRandom[42]; nums = RandomReal[100., 3000];
Mean[nums], mean[nums]}
{50.1012, 50.1012}
$\endgroup$
3
$\begingroup$

The problem with your code is, that n is a global variable and changes in each recursion step. This influences calculations on a higher recursion level. To avoid that you need to create a local variable n at each recursion step. You can do this by using for example Module or Block. Leaving your code pretty much untouched the result is:

Meen[x_] := 
 Module[{n}, 
  If[Length[x] == 1, Return[x],(*If condition is TRUE*)
   n = Length[x] - 1;
   result = 1/(n + 1)*(n*Meen[x[[1 ;; n]]] + x[[n + 1]])]]
$\endgroup$
2
$\begingroup$

Here is a straightforward way based on the formula you provided:

    mean[{x_}] := x;
    mean[{x_, y___}] := Block[{$RecursionLimit = Infinity}, 
                              (Length[{y}] * mean[{y}] + x)/ Length[{x, y}]]

Usage:

mean[{a, b, c, d}]

Gives:

1/4 (a + b + c + d)

using nums as defined by m_goldberg

mean[nums] == Mean[nums]

True

$\endgroup$
0
$\begingroup$

I accept that there are a number of reasons to define this function recursively, including desire to get intermediate results. Mathematica's Mean is very efficient (I appreciate this is likely not the intent). This recursive approach becomes very very slow for data size 1000000. A "recursive" approach (using the method):

mn[u_] := Module[
  {list},
  list = Thread[{u, Range[Length[u]]}];
  First@Fold[((#2[[2]] - 1) #1 + #2)/#2[[2]] &, First@list, Rest@list]]

OnRandomReal[1,1000000] takes 5.9 seconds...compared with 0. for Mean... I hve tried some of the other methods and my machine hungs up but do not take my word for it.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.