Math :: Complex搞砸了我的数组引用

use*_*453 1 arrays perl reference complex-numbers

我试图在这里优化一些代码,并编写了两个不同的简单子程序,它们将从另一个向量中减去一个向量.我将一对向量传递给这些子程序,然后执行减法.第一个子例程使用中间变量来存储结果,而第二个子例程使用' - ='运算符进行内联操作.完整代码位于此问题的底部.

当我使用纯粹的实数时,程序运行正常,没有问题.但是,如果我使用复杂的操作数,那么原始向量(最初传递给子例程的向量)将被修改!为什么这个程序适用于纯实数,但在使用复数时会进行这种数据修改?

注意我的过程:

  1. 生成随机向量(实际或复杂,具体取决于注释掉的代码)
  2. 将主矢量打印到屏幕上
  3. 执行第一个子程序减法(使用子程序中的第三个变量中间)
  4. 无论使用真实矢量还是复杂矢量,再次将主矢量打印到屏幕上以证明它们没有改变
  5. 执行第二个子程序减法(使用内联计算方法)
  6. 再次将主矢量打印到屏幕,显示使用复矢量时@ main_v1已更改,但使用实矢量时不会改变(@ main_v2不受影响)
  7. 打印减法的最终答案,无论是实数还是复数矢量,它们始终是正确的答案

出现这个问题是因为在第二个子程序(速度快得多)的情况下,我不希望@ main_v1向量发生变化.我需要那个矢量来进行进一步的计算,所以我需要它保持不变.

关于如何解决这个问题,或者我做错了什么?我的整个代码都在下面,应该是有用的.我一直在使用下面显示的CLI语法来运行程序.我选择5只是为了让我能够轻松阅读.

c:\> bench.pl 5 REAL

要么

c:\> bench.pl 5 IMAG

#!/usr/local/bin/perl
# when debugging: add -w option above
#

use strict;
use warnings;
use Benchmark qw (:all);
use Math::Complex;
use Math::Trig;
use Time::HiRes qw (gettimeofday);

system('cls');

my $dimension = $ARGV[0];
my $type = $ARGV[1];

if(!$dimension || !$type){
    print "bench.pl <n> <REAL | IMAG>\n";
    print "   <n> indicates the dimension of the vector to generate\n";
    print "   <REAL | IMAG> dictates to use real or complex vectors\n";
    exit(0);
}

my @main_v1;
my @main_v2;
my @vector_sum1;
my @vector_sum2;

for($a=1;$a<=$dimension;$a++){

    my $r1 = sprintf("%.0f", 9*rand)+1;
    my $r2 = sprintf("%.0f", 9*rand)+1;
    my $i1 = sprintf("%.0f", 9*rand)+1;
    my $i2 = sprintf("%.0f", 9*rand)+1;

    if(uc($type) eq "IMAG"){
        # Using complex vectors has the issue
        $main_v1[$a] = cplx($r1,$i1);
        $main_v2[$a] = cplx($r2,$i2);
    }elsif(uc($type) eq "REAL"){
        # Using real vectors shows no issue
        $main_v1[$a] = $r1;
        $main_v2[$a] = $r2;
    }else {
        print "bench.pl <n> <REAL | IMAG>\n";
        print "   <n> indicates the dimension of the vector to generate\n";
        print "   <REAL | IMAG> dictates to use real or complex vectors\n";
        exit(0);
    }
}

# cmpthese(-5, {
#   v1 => sub {@vector_sum1 = vector_subtract(\@main_v1, \@main_v2)},
#   v2 => sub {@vector_sum2 = vector_subtract_v2(\@main_v1, \@main_v2)},
# });
# print "\n";

print "main vectors as defined initially\n";
print_vector_matlab(@main_v1);
print_vector_matlab(@main_v2);
print "\n";

@vector_sum1 = vector_subtract(\@main_v1, \@main_v2);
print "main vectors after the subtraction using 3rd variable\n";
print_vector_matlab(@main_v1);
print_vector_matlab(@main_v2);
print "\n";

@vector_sum2 = vector_subtract_v2(\@main_v1, \@main_v2);
print "main vectors after the inline subtraction\n";
print_vector_matlab(@main_v1);
print_vector_matlab(@main_v2);
print "\n";

print "subtracted vectors from both subroutines\n";
print_vector_matlab(@vector_sum1);
print_vector_matlab(@vector_sum2);


sub vector_subtract {
    # subroutine to subtract one [n x 1] vector from another
    # result = vector1 - vector2
    # 
    my @vector1 = @{$_[0]};
    my @vector2 = @{$_[1]};
    my @result;

    my $row = 0;
    my $dim1 = @vector1 - 1;
    my $dim2 = @vector2 - 1;

    if($dim1 != $dim2){
        syswrite STDOUT, "ERROR: attempting to subtract vectors of mismatched dimensions\n";
        exit;
    }

    for($row=1;$row<=$dim1;$row++){$result[$row] = $vector1[$row] - $vector2[$row]}

    return(@result);
}

sub vector_subtract_v2 {
    # subroutine to subtract one [n x 1] vector from another
    # implements the inline subtraction method for alleged speedup
    # result = vector1 - vector2
    # 
    my @vector1 = @{$_[0]};
    my @vector2 = @{$_[1]};

    my $row = 0;
    my $dim1 = @vector1 - 1;
    my $dim2 = @vector2 - 1;

    if($dim1 != $dim2){
        syswrite STDOUT, "ERROR: attempting to subtract vectors of mismatched dimensions\n";
        exit;
    }
    for($row=1;$row<=$dim1;$row++){$vector1[$row] -= $vector2[$row]}        # subtract inline

    return(@vector1);
}

sub print_vector_matlab {       # for use with outputting square matrices only
    my (@junk) = (@_);
    my $dimension = @junk - 1;
    print "V=[";
    for($b=1;$b<=$dimension;$b++){
        # $temp_real = sprintf("%.3f", Re($junk[$b][$c]));
        # $temp_imag = sprintf("%.3f", Im($junk[$b][$c]));
        # $temp_cplx = cplx($temp_real,$temp_imag);
        print "$junk[$b];";
        # print "$temp_cplx,";
    }
    print "];\n";
}
Run Code Online (Sandbox Code Playgroud)

我甚至尝试修改第二个子程序,使其具有以下行,并且当使用复数时,它仍然会改变@ main_v1向量...我对发生了什么感到困惑.

@result = @vector1;
for($row=1;$row<=$dim1;$row++){$result[$row] -= $vector2[$row]}

return(@result);
Run Code Online (Sandbox Code Playgroud)

我也试过了......仍然用复数修改@ main_V1

for($row-1;$row<=$dim1;$row++){$result[$row] = $vector1[$row]}
for($row=1;$row<=$dim1;$row++){$result[$row] -= $vector2[$row]}

return(@result);
Run Code Online (Sandbox Code Playgroud)

Ale*_*nii 5

将Math :: Complex升级到至少1.57版.正如更改日志所解释的那样,该版本的一个变化是:

添加复制构造函数并安排适当调用它,David Madore和Alexandr Ciornii发现问题.