Averages/Arithmetic mean: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Common Lisp}}: Simpler version using apply)
(→‎{{header|Common Lisp}}: replaced; now applicable to all sequence types and uses REDUCE, not APPLY (good practice); 'sum-list' is gone as it had bad syntax)
Line 80: Line 80:
=={{header|Common Lisp}}==
=={{header|Common Lisp}}==


(defun mean (sequence)
This example uses a recursive sum-list function.
(let ((length (length sequence)))

(if (zerop length)
(defun sum-list (list)
(if (list)
0
(+ (car list) (sum-list (cdr list)))
(/ (reduce #'+ sequence) length))))
0))
(defun mean (list)
(/ (sum-list list) (length list)))

However the following works as well:

(defun mean (list)
(if list
(/ (apply '+ list) (length list))
0))


=={{header|Forth}}==
=={{header|Forth}}==

Revision as of 20:33, 10 February 2008

Task
Averages/Arithmetic mean
You are encouraged to solve this task according to the task description, using any language you may know.

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).

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++

Library: STL
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))))

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

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));
...

OCaml

These functions return a float:

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)

Perl

sub avg(@_) {
  $count = 0;
  $sum = 0;
  foreach (@_) {
    $sum += $_;
    $count++;
  }
  return $count > 0 ? $sum / $count : 0;
}

print avg(qw(3 1 4 1 5 9))."\n";

Output:

3.83333333333333

With module Data::Average. (For zero-length array returns ().)

use Data::Average;

my $d = Data::Average->new;
$d->add($_) foreach (qw(3 1 4 1 5 9));
print $d->avg."\n"

Output:

3.83333333333333