Calculate the average of a series

From CodeCodex

Revision as of 21:33, 15 February 2011 by 79.91.219.32 (Talk)

Related content:

Implementations

Assembly

Integers

Following the description for the ANSI C version, except that INT_MAX here is always 2147483647 (0x7FFFFFFF). Formatted in MASM, only returns an integer value.

avg proc
	mov edx,esp
	add edx,4
	avg_loop1:
	add eax,DWORD PTR [edx]
	add edx,4
	cmp DWORD PTR [edx],7fffffffh
	jne avg_loop1
	mov ecx,DWORD PTR [esp]
	xchg esp,edx
	sub edx,esp
	add esp,4
	push ecx
	neg edx
	shr edx,2
	mov ecx,edx
	xor edx,edx
	sub ecx,1
	div ecx
	ret
avg endp

Using the FPU

This leaves the result in st(0) - caller has to free it.

avg proc
	mov ecx,DWORD PTR [esp]
	add esp,4
	mov edx,esp
	fldz
	avg_loop1:
	fild DWORD PTR [esp]
	fadd
	add esp,4
	cmp DWORD PTR [esp],7fffffffh
	jne avg_loop1
	sub edx,esp
	neg edx
	shr edx,2
	mov DWORD PTR [esp],edx
	fild DWORD PTR [esp]
	fdiv
	mov DWORD PTR [esp],ecx
	ret
avg endp

C

This particular function averages all integers until a INT_MAX is passed as an argument. INT_MAX is used because it is a very large number that is most likely to not be naturally part of an average. Since INT_MAX is defined by nearly all compilers, you should be able to call this function relatively easily, e.g. average(4,5,6,INT_MAX);

//stdarg.h must be included for this type of function to be declared
#include <stdarg.h>

double average( int first, ... ) {
   int count = 0, sum = 0, i = first;
   va_list marker;

   va_start( marker, first );     /* Initialize variable arguments. */
   while( i != INT_MAX )
   {
      sum += i;                   //increases the sum
      count++;                    //increases the count
      i = va_arg( marker, int);   //Gets the next argument
   }
   va_end( marker );              // Resets the list
   return( sum ? ((double)sum / count) : 0.0 );
}

C++

#include <numeric>

template <typename Iterator>
double average(Iterator begin, Iterator end) {
  return std::accumulate(begin, end, 0.0) / (end - begin);
}

Common Lisp

> (defun average (list) (/ (reduce #'+ list) (length list)))
AVERAGE
> (average '(1 2 3 4))
5/2
> (average '(1 2 3 4.0))
2.5

Erlang

average(List) ->
    lists:sum(List) / length(List).

Excel

=AVERAGE([cells])

Haskell

Sum a list of numbers and divide by the length of the list:

avg l = sum l / List.genericLength l

Java

This implementation can only be used with java version 1.5.0 (a.k.a java 5.0) since this new version implements varargs.

import java.util.*;

public class Averages {

    public static int average(int... values) {
        double sum = 0;
        for (int i : values) {
            if (i == Integer.MAX_VALUE) break;
            sum += i;
          
        }
        return (int) Math.round(sum/(values.length-1)); //Math.round is used for rounding
    }

    public static void main(String[] args) {

        System.out.printf("Average: %d: ", average(1,2,4,40,Integer.MAX_VALUE));
        
    }
}

OCaml

Sum a list of integers and divide by the length of the list:

# let avg l = float(List.fold_left ( + ) 0 l) /. float(List.length l);;
val avg : int list -> float = <fun>

For example:

# avg [1;2;4;8;16];;
- : float = 6.2

Perl

use List::Util 'sum';

# Pass the list directly as the argument list
print average(1 .. 3);

sub average {
	my @array = @_;
	return sum(@array) / @array;
}

Python

This python function returns the average of an arbitrary sequence, a wikipedia:Generator (computer science) too:

def average(seq, total=0.0):
    num = 0
    for item in seq:
        total += item
        num += 1
    return total / num

If seq is sequence type such as a list or a tuple, you can calculate its average just like this:

def average(seq):
  return float(sum(seq)) / len(seq)

The float() call is required to coerce the division into being a floating point, and not integer division. In python 3 all numeric divisions will be floating point divisions, and the // operator will be used to mean purely integer division.

REXX

/* Calculating average in REXX */

sum = 0.0
n = 0
do loop until figure = 0
    pull figure
    sum = sum + figure
    n = n + 1
end do
n = n - 1
average = sum / n
say "Average =" average

Ruby

def average(sequence)
  sequence.inject(:+).to_f / sequence.length
end

(Although it Ruby also knows @for ... in@, you should not use it unless you know why you're doing it.)

Scheme

(define (average list)
  (/ (apply + list) (length list)))

Tcl

proc average list {expr ([join $list +])/[llength $list].}

or

namespace import ::tcl::mathop::*
proc average list {expr {[+ {*}$list]/double([llength $list])}}

Zsh

average() {
	local -a array
	local -F1 sum
	array=({1..9})
	(( sum = (${(j:+:)array}.0) / ${(w)#array} ))
	print "$sum"
}