#!/usr/bin/perl -w # # avg: calculate all the standard features of a list of numbers. # This includes the maximum, mean, median, minimum, mode, standard # deviation, and sum. # # http://gonze.com/blog/code/stats # # Changelog: # May 13, 2003: created changelog # # Contact: # Lucas Gonze use strict; # ugly workaround for emacs indentation bug -- cperl-mode can't handle a # dollar sign at the end of a regex, so put the character in a var and # reference the var . my $dollar = "\$"; ########## # input my @numbers; while (<>) { chomp(); # trim leading and trailing whitespace s/(^\s*)(.*)(\s*$dollar)/$2/g; # trim trailing CR caused by windows-unix conversion s/(.*)(\r$)/$1/g; # skip comments and blanks if (/(\#)(.*)/ || /^$/) { next; } push(@numbers, $_ + 0); } my $cnt = $#numbers + 1; if ($cnt < 1) { print "No input\n"; exit(1); } ########## # average my $sum = 0; for my $number (@numbers) { $sum += $number; } my $average = $sum / $cnt; ########## # median my $median = $numbers[$cnt / 2]; ########## # standard deviation my $stddev = 0; if ($cnt < 2) { # Only 1 number? $stddev = "UNDEFINED"; } else { for my $number (@numbers) { $stddev = $stddev + ($number - $average)**2; } $stddev = sqrt($stddev / ($cnt + 1)); } ########## # mode my $mode = $numbers[0]; my %histo; for my $number (@numbers) { if (!$histo{$number}) { $histo{$number} = 1; } else { $histo{$number} += 1; } if ($histo{$number} > $histo{$mode}) { $mode = $number; } } ########## # min and max my $min = $numbers[0]; my $max = $numbers[0]; for my $number (@numbers) { if ($number < $min) { $min = $number; } if ($number > $max) { $max = $number; } } ########## # output print <