#!/usr/bin/perl -w
# turn on strict forcing definition of variables and subs/functions
use strict;
#
# Declare Function/Sub Routines
sub Mean ; #Given input array return the mean, that is sum of
# elements divided by number of elements.
#
sub Median ; #Given input array return the Median, that is the value
# which has 50 percent of the elements above and 50 percent below.
#
sub Mode; #Given input array return the value that occurs most
# frequently or return NONE if no duplicates.
#
sub Sample_standard_dev; #Given Input of Mean and Sum_of the differences of the
# Mean Squared, return the Sample Standard Deviation.
# Sample Standard Deviation = SQRT( (Sum_of( X - Mean)**2) / (N - 1) )
# Note, divide by N - 1 for the Bessel Correction for a finite sample.
#
sub Sum_of; #Given an input Array and the Mean, calculate the total
# sum of (X - Mean)**2 for each value in the Array.
# This returns the Total value of the difference of the Squares.
#
#Sub Routine / Function Section
sub Mean # Returns Arithmetic mean sum of Elements/num of elements
# Input is an array
{
my $Mean_value = 0;
my $knum = 0; #Number of elements in Array.
my $j = 0; #iteration loop scalar counter
my $result = 0 ; # initialize sum for array
my @input_array = @_;
$knum = scalar@input_array; #Get number of elements in array.
if ( $knum < 2 ){
printf " Must have an input array with at least two elements ";
exit;
}
# Note we must subtract -1 from $knum so we do not go past the
# end of the search array.
for ( $j = 0; $j <= ($knum -1 ); $j++)
{
$result += $input_array[$j];
}
$Mean_value = $result/$knum ;
$Mean_value = sprintf ("%.2f", $Mean_value) ; # Trim of the floating point stuff after two decimal points.
return $Mean_value; #
} # End sub Mean
#
sub Sum_of # Returns a Value for the sum of the mean squared differences
# Input is a Mean Value followed by an Array.
{
my $knum = 0; #Number of elements in Array.
my $j = 0; #iteration loop scalar counter
my $result = 0 ; # initialize sum of mean squared differences
# for array
my $sum_squared_diff = 0;
my ($Average, @input_ar ) = @_ ;
$knum = scalar@input_ar; #Get number of elements in array.
if ( $knum < 2) {
printf " Must have an input array with at least two elements ";
exit;
}
# Note we must subtract -1 from $knum so we do not go past the
# end of the search array.
for ( $j = 0; $j <= ($knum -1 ); $j++)
{
$result += ($input_ar[$j] - $Average ) **2;
}
$sum_squared_diff = $result;
return $sum_squared_diff;
} # End sub Sum_of
#
sub Sample_standard_dev
{
my $result = 0;
my $Sample_dev = 0;
my ($Sum_squared_diff, $num_of_elements ) = @_ ; # Input Sum Squared differences
# Number of elements in Array
if ($num_of_elements < 2 ) {
printf "Array must have at least two elements, exiting now! \n";
exit;
}
$result = sqrt ($Sum_squared_diff / ($num_of_elements - 1 ) );
$result = sprintf ("%.2f", $result) ; # Trim of the floating point stuff after two decimal points.
return $Sample_dev = $result;
} # End Sample_standard_dev
#
#
sub Median
{
my @array_in = @_;
my @sorted_array = ();
my $knum = 0; #Number of elements in Array.
my $median = 0;
my $j = 0; #iteration loop scalar counter
my $result = 0 ; # initialize median element
@sorted_array = sort { $a <=> $b } @array_in ; # numerical sort
# force numeric sort here, note $a and $b or special variables and do not have to initialized!
printf " This is the Sorted Array: @sorted_array \n";
$knum = scalar@sorted_array; #Get number of elements in array.
if ( $knum < 2) {
printf " Must have an input array with at least two elements ";
exit;
}
$knum-- ; # Decrement it because otherwise we go beyond the array
# remember $knum = 0 is first element;
$j = int (($knum/2) + 0.5); #Force rounding up of index with int function
$result = $sorted_array[$j] ;
$median = $result;
return $median ;
} # End Sub Median
#
sub Mode
#Input is an Array
# This will print out as part of calling the Function the
# Mode (Key Value pair) , stating the value which occurs and
# and its frequency.
{
# Storage initialization
my $do_while = "TRUE";
my $freq = "999";
my $store_freq = "999";
my @values = ();
my $result = "NADA";
my $j = 0; # number of value key pairs in Hash list
my @Max_mode_values; # used to store mode values that occur more than once
my @array = @_ ;
my $num_of_hash_pairs = scalar@array;
my %hash_count = qw ( ) ;
# Previous intializes the hash list, which will be a value , followed by
# the number of occurences.
my $key_val = "NONE"; # Assume nothing will be found for now.
# Note, $a and $b are special Perl variables, used in
# sorting hashes so we do not have to define them!
# we store the values and their frequency in a hash
map{ $hash_count{$_}++ } @array;
# sort the hash by values
# Using the special variables $a and $b built in , compare with the
# <=> (numerical compare operator) any two consecutive values in the
# hash list sorting ascending, it would $b and $a if you were doing
# descending...
# and sort them, you keep doing this to generate a sorted hash list.
# Don't worry about the details, Perl takes care of it for you.
#
for $key_val ( sort {$hash_count{$a} <=> $hash_count{$b}} keys %hash_count ) {
if ($hash_count{$key_val} > int(1) ) {
# push @AoH, { husband => "fred", wife => "wilma", daughter => "pebbles" };
push ( @Max_mode_values, "$key_val , $hash_count{$key_val}" ) ;
$j++ ;# To get a count of how many values you pushed into push array
# push ( @Max_mode_values, " $key_val occurs $hash_count{$key_val} times \n" ) ;
}
}
# printf " @Max_mode_values \n";
# uncomment previous to prove algorithm works, to print all modes.
# Do first pop , this will always be done!
$result = pop (@Max_mode_values);
@values = split(',', $result);
$freq = $values[1];
# printf " This is the frequency: $freq \n";
printf " $values[0] occurs $freq times \n";
$store_freq = $freq; # save frequency
while ($do_while eq "TRUE")
{
$result = pop (@Max_mode_values);
@values = split(',', $result);
$freq = $values[1];
if ($store_freq != $freq) {
$do_while = "FALSE";
next ; # This will terminate the while loop!
}
# otherwise we still have more frequencies to print that are at
# the maximum value.
# printf " This is the frequency: $freq \n";
printf " $values[0] occurs $freq times \n";
# printf " This is store_freq: $store_freq and this is frequency: $freq \n";
$store_freq = $freq; # store the frequency we just got and printed.
}
return; # break out of called routine for safety, you should never get
# here;
}
# End Sub Mode
#
# Main Section
# my @input_array_values = ( 1, 2, 5, 9, 2, 8, 3);
# Use a randomly generated array
my $i = 0; # array index 0.. $array_num_of_elements - 1
my $range = 100; # This says what will be the maximum value we can get
my $min_value = 1; # similarly this is the minimum value we can get
my $array_num_of_elements = 300;
my @random_number = ();
for ($i = 0; $i < $array_num_of_elements ; $i++)
{
# Note, rand will return 0 so we add a 1 to it to force it to
# be that minimum value.
$random_number[$i] = int( $min_value + rand($range));
}
my @input_array_values = @random_number;
my $num_of_array_elements = scalar@input_array_values ;
my $Mean_is = 0;
my $Median_is = 0;
my $Sum_squared_diff_is = 0;
my $Sample_dev = 0;
printf "\n Note, all calculations are done to two decimal places. \n" ;
printf "\n This is the orginal array: @input_array_values \n" ;
$Mean_is = Mean( @input_array_values);
$Median_is = Median( @input_array_values) ;
printf " The mean is $Mean_is and the Median is $Median_is \n";
printf " The Greatest Mode Values are: \n";
Mode(@input_array_values);
# Previous will return the Mode saying what it is and how many times
# it occurs.
$Sum_squared_diff_is = Sum_of($Mean_is, @input_array_values );
printf " \n The Sum Squared differences value is: $Sum_squared_diff_is \n" ;
$Sample_dev = Sample_standard_dev( $Sum_squared_diff_is, $num_of_array_elements);
printf " The Sample Standard Deviations is: $Sample_dev \n" ;
exit;