使用perl减少来计算点积

时间:2013-01-15 21:54:44

标签: perl dot-product

假设我的perl程序中有以下两个大小相等的数组:

my @arr1 = 1..5;
my @arr2 = 6..10;

我正在尝试使用reduce核心模块中定义的List::Util函数来获取他们的点积,但以下内容对我不起作用:

my $dot_prod = reduce { $arr1[$a] * $arr2[$a] + $arr1[$b] * $arr2[$b] }0..$#arr1;

我的输出 50 而不是预期的 130

3 个答案:

答案 0 :(得分:6)

documentation描述了reduce的行为,如下所示:

  

第一个调用将是$ a和$ b设置为前两个元素   在列表中,后续调用将通过将$ a设置为结果来完成   上一次调用,$ b到列表中的下一个元素。

因此,在这种情况下,在第一次迭代reduce将设置$a = 0$b = 1,因此,执行

$arr1[0] * $arr2[0] + $arr1[1] * $arr2[1] 

这个临时结果恰好是 20

现在,对于第二次迭代,$a设置为上一次迭代的结果,因此$a = 20$b = 2。因此,将执行以下操作

$arr1[20] * $arr2[20] + $arr1[2] * $arr2[2]

我们想要的东西。

可能的解决方法:

将初始0添加到作为reduce的输入提供的列表中,如下所示:

my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1;       

这给了我们预期的结果,因为在第一次迭代$a = $b = 0上我们将计算

0 + $arr[0] * $arr[0]

其结果将 6

然后在第二次迭代中,我们将$a = 6 $b = 1,因此我们将计算

6 + $arr1[1] * $arr2[1]

答案 1 :(得分:0)

真的,

my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1; 

不是最易读的。有这个:

my $dot_prod = sum map { $arr1[$_]*$arr2[$_] } 0..$#arr1;

但那不使用reduce。好吧,我们可以简单地用sum来实现reduce而不是使用List :: Util,甚至可以内联它:

my $dot_prod = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1;

但这三种解决方案中没有一种纯粹是功能性的。

答案 2 :(得分:0)

my @arr1 = 1..3;
my @arr2 = 6..8;

use List::Util qw(reduce sum) ;

my $dot_prod0 = reduce { $a + $arr1[$b] * $arr2[$b] } 0,0..$#arr1;       #reduce

print "Dot product0 = ".$dot_prod0."\n";
my $dot_prod1 = sum map  { $arr1[$_]*$arr2[$_] } 0..$#arr1;              #sum map
print "Dot product1 = ".$dot_prod1."\n";
my $dot_prod2 = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1;  #reduce map
print "Dot product2 = ".$dot_prod2."\n";