sub show_histogram { # Prints a simple text histogram given a reference # to an array of integers. # Larry Leszczynski my ($array_ref, $binsize, $width) = @_; $binsize ||= 1; $width ||= 50; use POSIX qw(ceil floor); # Divide input data into bins: my %bin_count = (); # number of items in each bin foreach ( @$array_ref ) { my $bin = floor(($_+.5)/$binsize); $bin_count{$bin}++; } my $max_items = 0; # maximum items in a single bin foreach ( values %bin_count ) { $max_items = $_ if $_ > $max_items; } # Try to keep histogram on one page width: my $scale = 1; if ( $max_items > $width ) { if ( $max_items <= ($width*5) ) { $scale = 5; } else { while ( ($max_items/$scale) > $width ) { $scale *= 10; } } } my @bins = sort {$a <=> $b} keys %bin_count; my $bin = $bins[0]; # lowest value bin my $maxbin = $bins[-1]; # highest value bin my $binfmt_width = ( length $maxbin > length $bin ) ? length $maxbin : length $bin; my $cntfmt_width = length $max_items; my $start = $bin * $binsize; my $end = $start + $binsize - 1; do { my $count = $bin_count{$bin} || 0; my $extra = ( $count % $scale ) ? '.' : ''; printf "%*d .. %*d \[%*d\] %s$extra\n", $binfmt_width, $start, $binfmt_width, $end, $cntfmt_width, $count, '#' x ceil($count/$scale); $start += $binsize; $end += $binsize; } while ( $bin++ < $maxbin ); print "\n Scale: #=$scale\n" if $scale > 1; }