Then, you can even iterate a few times centering the interval around the best average ($best_avg) found:use POSIX qw(fmod); my @data = (1, 1, 1, 0, 1, 2, 3, 4, 21, 22, 20, 22, 23, 20, 22); sub circular_average { my ($pivot, $round, @data) = @_; my $sum = 0; my $sum2 = 0; my $displacement = 1.5 * $round - $pivot; for my $data (@data) { my $displaced = fmod($data + $displacement, $round); # printf "%2i->%3i,%2i ", $data, $displaced, $displaced - $dis +placement; $sum += $displaced; $sum2 += $displaced * $displaced; } # print "\n"; my $inv_n = 1.0 / @data; my $avg = fmod($inv_n * $sum + 0.5 * $round + $pivot, $round); wantarray ? ($avg, $inv_n * $sum2 - $inv_n * $inv_n * $sum * $sum) + : $avg; } my ($best_avg, $best_s2); for my $time (0..23) { my ($avg, $s2) = circular_average $time, 24, @data; if (not defined $best_s2 or $best_s2 > $s2) { $best_avg = $avg; $best_s2 = $s2; } } printf "avg: %.1f, s2: %.1f\n", $best_avg, $best_s2;
for (0..5) { ($best_avg, $best_s2) = circular_average $best_avg, 24, @data; printf "avg: %.1f, s2: %.1f\n", $best_avg, $best_s2; }
In reply to Re: Average start time handling midnight
by salva
in thread Average start time handling midnight
by chrisjej
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |