#!/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;