Averages/Arithmetic mean
Write a program to find the mean (arithmetic average) of a numeric vector. The program should work on a zero-length vector (with an answer of 0).
You are encouraged to solve this task according to the task description, using any language you may know.
Ada
This example shows how to pass a zero length vector as well as a larger vector.
with Ada.Float_Text_Io; use Ada.Float_Text_Io; with Ada.Text_IO; use Ada.Text_IO; procedure Mean_Main is type Vector is array(Positive range <>) of Float; function Mean(Item : Vector) return Float is Sum : Float := 0.0; Result : Float := 0.0; begin for I in Item'range loop Sum := Sum + Item(I); end loop; if Item'Length > 0 then Result := Sum / Float(Item'Length); end if; return Result; end Mean; A : Vector := (3.0, 1.0, 4.0, 1.0, 5.0, 9.0); begin Put(Item => Mean(A), Fore => 1, Exp => 0); New_Line; -- test for zero length vector Put(Item => Mean(A(1..0)), Fore => 1, Exp => 0); New_Line; end Mean_Main;
Output:
3.83333 0.00000
BASIC
Assume the numbers are in a DIM named nums.
mean = 0 sum = 0; FOR i = LBOUND(nums) TO UBOUND(nums) sum = sum + nums(i); NEXT i size = UBOUND(nums) - LBOUND(nums) + 1 PRINT "The mean is: "; IF size <> 0 THEN PRINT (sum / size) ELSE PRINT 0 END IF
C
This implementation uses a plain old static array of doubles for the numeric vector.
<c>#include <stdio.h>
double mean(double *p, unsigned qty) /* Calculates the mean of qty doubles beginning at p. */
{if (qty == 0) return 0; double total = 0; for (int i = 0 ; i < qty ; ++i) total += p[i]; return total / qty;}
int main(void)
{double test[6] = {1.0, 2.0, 5.0, -5.0, 9.5, 3.14159}; printf("%lg\n", mean(test, 6)); return 0;}</c>
C++
double mean(std::vector<double> const& vNumbers) { double sum = 0; for( std::vector<double>::iterator i = vNumbers.begin(); vNumbers.end() != i; ++i ) sum += *i; if( 0 == vNumbers.size() ) return 0; else return sum / vNumbers.size(); }
Shorter (and more idiomatic) version:
#include <vector> #include <algorithm> double mean(std::vector<double> const& numbers) { if (numbers.empty()) return 0; return std::accumulate(numbers.begin(), numbers.end(), 0.0) / numbers.size(); }
Common Lisp
(defun mean (sequence) (let ((length (length sequence))) (if (zerop length) 0 (/ (reduce #'+ sequence) length))))
D
Using template to make the mean function work for higher-rank array.
module mean ; import std.stdio ; real mean(T)(T[] a) { static if(is(T U : U[])) { // recursively unfold the multi-array T u ; foreach(e ; a) u ~= e ; return u.mean() ; } else { // do the math if(a.length == 0) return 0.0 ; real sum = 0.0 ; foreach(e ; a) sum += e ; return sum / a.length ; } } void main() { int[] array = [3,1,4,1,5,9]; real[][][] multi = [[[1,2,2],[2,3,4],[4,5,7]], [[4,1,3],[0,3,1],[4,4,6]], [[1,3,3],[2,7,8],[9,1,5]]] ; writefln("array : ", array.mean()) ; writefln("multi : ", multi.mean()) ; }
Forth
: fmean ( addr n -- f ) 0e dup 0= if 2drop exit then tuck floats bounds do i f@ f+ 1 floats +loop 0 d>f f/ ; create test 3e f, 1e f, 4e f, 1e f, 5e f, 9e f, test 6 fmean f. \ 3.83333333333333
Fortran
In ISO Fortran 90 or later, use the SUM intrinsic, the SIZE intrinsic and the MAX intrinsic (to avoid divide by zero):
real, target, dimension(100) :: a = (/ (i, i=1, 100) /) real, dimension(5,20) :: b = reshape( a, (/ 5,20 /) ) real, pointer, dimension(:) :: p => a(2:1) ! pointer to zero-length array real :: mean, zmean, bmean real, dimension(20) :: colmeans real, dimension(5) :: rowmeans mean = sum(a)/size(a) ! SUM of A's elements divided by SIZE of A mean = sum(a)/max(size(a),1) ! Same result, but safer code ! MAX of SIZE and 1 prevents divide by zero if SIZE == 0 (zero-length array) zmean = sum(p)/max(size(p),1) ! Here the safety check pays off. Since P is a zero-length array, ! expression becomes "0 / MAX( 0, 1 ) -> 0 / 1 -> 0", rather than "0 / 0 -> NaN" bmean = sum(b)/max(size(b),1) ! multidimensional SUM over multidimensional SIZE rowmeans = sum(b,1)/max(size(b,2),1) ! SUM elements in each row (dimension 1) ! dividing by the length of the row, which is the number of columns (SIZE of dimension 2) colmeans = sum(b,2)/max(size(b,1),1) ! SUM elements in each column (dimension 2) ! dividing by the length of the column, which is the number of rows (SIZE of dimension 1)
Haskell
mean xs = sum xs / Data.List.genericLength xs
IDL
If truly only the mean is wanted, one could use
x = [3,1,4,1,5,9] print,mean(x)
But mean() is just a thin wrapper returning the zeroth element of moment() :
print,moment(x) ; ==> 3.83333 8.96667 0.580037 -1.25081
which are mean, variance, skewness and kurtosis.
There are no zero-length vectors in IDL. Every variable has at least one value or otherwise it is <Undefined>.
J
mean=: +/ % #
That is, sum divided by the number of items. The verb also works on higher-ranked arrays. For example:
mean 3 1 4 1 5 9 3.83333 mean $0 NB. $0 is a zero-length vector 0 x=: 20 4 ?@$ 0 NB. a 20-by-4 table of random (0,1) numbers mean x 0.58243 0.402948 0.477066 0.511155
The computation can also be written as a loop. It is shown here for comparison only and is highly non-preferred compared to the version above.
mean1=: 3 : 0 z=. 0 for_i. i.#y do. z=. z+i{y end. z % #y ) mean1 3 1 4 1 5 9 3.83333 mean1 $0 0 mean1 x 0.58243 0.402948 0.477066 0.511155
Java
Assume the numbers are in a double array called "nums".
... double mean = 0; double sum = 0; for(double i : nums){ sum += i; } System.out.println("The mean is: " + ((nums.length != 0) ? (sum / nums.length) : 0)); ...
JavaScript
function mean(array) { var sum = 0; for(var i in array) sum += array[i]; return array.length ? sum / array.length : 0; } alert( mean( [1,2,3,4,5] ) ); // 3
function mean(a) { return a.length ? Functional.reduce('+', 0, a) / a.length : 0; }
Logo
to average :l if empty? :l [output 0] output quotient apply "sum :l count :l end print average [1 2 3 4] ; 2.5
Lucid
avg(x) where sum = first(x) fby sum + next(x); n = 1 fby n + 1; avg = sum / n; end
MAXScript
fn mean data = ( total = 0 for i in data do ( total += i ) if data.count == 0 then 0 else total as float/data.count ) print (mean #(3, 1, 4, 1, 5, 9))
Nial
in the standard way, mean is
mean is / [sum, tally]
mean 6 2 4 = 4
but it fails with 0 length vectors. so using a tally with a minimum value 1
dtally is recur [ empty rest, 1 first, 1 first, plus, rest ] mean is / [sum, dtally]
mean [] =0
OCaml
These functions return a float:
<ocaml>let mean_floats xs =
if xs = [] then 0. else List.fold_left (+.) 0. xs /. float_of_int (List.length xs)
let mean_ints xs = mean_floats (List.map float_of_int xs)</ocaml>
the previous code is easier to read and understand, though if you which the fastest implementation to use in production code notice several points: it is possible to save a call to List.length computing the length through the List.fold_left, and for mean_ints it is possible to save calling float_of_int on every numbers, converting only the result of the addition. (also when using List.map and the order is not important, you can use List.rev_map instead to save an internal List.rev.) Also the task asks to return 0 on empty lists, but in OCaml this case would rather be handled by an exception.
<ocaml>let mean_floats xs =
if xs = [] then invalid_arg "empty list" else let total, length = List.fold_left (fun (tot,len) x -> (x +. tot), len +. 1.) (0., 0.) xs in (total /. length)
let mean_ints xs =
if xs = [] then invalid_arg "empty list" else let total, length = List.fold_left (fun (tot,len) x -> (x + tot), len +. 1.) (0, 0.) xs in (float total /. length)
- </ocaml>
Perl
<perl>sub avg {
@_ or return 0; my $sum = 0; $sum += $_ foreach @_; return $sum/@_;
}
print avg(qw(3 1 4 1 5 9)), "\n";</perl>
With module Data::Average. (For zero-length arrays, returns the empty list.) <perl>use Data::Average;
my $d = Data::Average->new; $d->add($_) foreach qw(3 1 4 1 5 9); print $d->avg, "\n";</perl>
Pop11
define mean(v); lvars n = length(v), i, s = 0; if n = 0 then return(0); else for i from 1 to n do s + v(i) -> s; endfor; endif; return(s/n); enddefine;
Python
<python>def average(x):
return sum(x)/float(len(x)) if x else 0
print average([3,1,4,1,5,9])</python>
Output:
<python>3.83333333333333</python>
<python>def avg(data): if len(data)==0: return 0 else: return sum(data)/float(len(data)) print avg([3,1,4,1,5,9])</python>
Output:
<python>3.83333333333333</python>
Ruby
nums = [3, 1, 4, 1, 5, 9] nums.empty? ? 0 : nums.inject(:+) / Float(nums.size)
Scheme
(define (mean l) (if (null? l) 0 (/ (apply + l) (length l))))
> (mean (list 3 1 4 1 5 9)) 3 5/6
UnixPipes
term() { b=$1;res=$2 echo "scale=5;$res+$b" | bc }
sum() { (read B; res=$1; test -n "$B" && (term $B $res) || (term 0 $res)) }
fold() { func=$1 (while read a ; do fold $func | $func $a done) }
mean() { tee >(wc -l > count) | fold sum | xargs echo "scale=5;(1/" $(cat count) ") * " | bc }
(echo 3; echo 1; echo 4) | mean
V
[mean [sum 0 [+] fold]. dup sum swap size [[1 <] [1]] when / ].