我有以下脚本:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(sum);
my @a1=([1,2,3],
[4,5,6],
[7,8,9]);
my @a2=([4,3],
[2,1]);
my @subtracted;
for (my $i=0; $i<=$#a2; $i++){
for (my $j=0; $j<=$#a2; $j++){
my $subtraction=$a1[$i][$j] - $a2[$i][$j];
print "$subtraction\n";
my $abs=abs($subtraction);
push(@subtracted, $abs);
}
}
my $sum=sum(@subtracted);
my $average=$sum/@subtracted;
print "Average=$average\n";
exit;
此打印:
-3
-1
2
4
Average=2.5
这将减去以下引用的元素:
$a1[0][0] - $a2[0][0]
$a1[0][1] - $a2[0][1]
$a1[1][0] - $a2[1][0]
$a1[1][1] - $a2[1][1]
但是现在我需要它来做
$a1[1][1] - $a2[0][0]
$a1[1][2] - $a2[0][1]
$a1[2][1] - $a2[1][0]
$a1[2][2] - $a2[1][1]
并打印:
1
3
6
8
Average=4.5
因此,@ a2的元素是固定的,但@ a1的元素却移动了1行和1列(比较的元素数始终受@ a2中的元素数限制)。但是现在我完全被困住了,不知道如何去做。因此,预先感谢您的想法。
答案 0 :(得分:1)
my $sum = 0;
for my $i (0..$#a2) {
for my $j (0..$#{ $a2[0] }) {
my $diff = $a1[$i+1][$j+1] - $a2[$i][$j];
$sum += $diff;
}
}
my $avg = $sum / ( @a2 * @{ $a2[0] } );
say "avg: $avg";
在评论中,您谈论要一个循环。目前尚不清楚这是什么意思,但我认为您的意思是想为每个可能的偏移量循环。
my $n = @a2;
my $m = @{ $a2[0] };
for my $ofs (0..$#a1-$#a2) {
my $sum = 0;
for my $i (0..$n-1) {
for my $j (0..$m-1) {
my $diff = $a1[$i+$ofs][$j+$ofs] - $a2[$i][$j];
$sum += $diff;
}
}
my $avg = $sum / ( $n * $m );
say "ofs: $ofs, avg: $avg";
}
一个偏移量之和中的许多术语与上一个偏移量之和相同。
如您所见,与从头计算总和相比,计算两个后续总和的增量所涉及的操作更少。我们可以利用它来优化大型阵列的解决方案。
my $n = @a2;
my $m = @{ $a2[0] };
my $nm = $n * $m;
my $sum = 0;
for my $i (0..$n-1) {
for my $j (0..$m-1) {
$sum -= $a2[$i][$j];
}
}
for my $i (0..$n-2) {
for my $j (0..$m-2) {
$sum += $a1[$i][$j];
}
}
for my $ofs (0..$#a1-$#a2) {
$sum += $a1[ $_ + $ofs ][ ($m-1) + $ofs ] for 0..$n-2;
$sum += $a1[ ($n-1) + $ofs ][ $_ + $ofs ] for 0..$m-2;
$sum += $a1[ ($n-1) + $ofs ][ ($m-1) + $ofs ];
my $avg = $sum / $nm;
say "ofs: $ofs, avg: $avg";
$sum -= $a1[ $_ + $ofs ][ 0 + $ofs ] for 1..$n-1;
$sum -= $a1[ 0 + $ofs ][ $_ + $ofs ] for 1..$m-1;
$sum -= $a1[ 0 + $ofs ][ 0 + $ofs ];
}
要处理大量数字,您可能需要查看PDL。