1

私はいくつかの方法を作りました。重心を計算し、重心に従って行列を変換します。重心の計算は正常に機能します。x、y、z の値は問題ありません。ただし、translateMatrixOperation サブメソッドでの配列の受け渡しに問題があります。基本的に、translateMatrixOperation は (\@translatematrix) を返し、サブメソッドを呼び出す別のメソッドの要素にアクセスできません。ここで何が問題なのですか?

my @ref = calculateCenterMass(@matrix);
my $x = $ref[0];
my $y = $ref[1];
my $z = $ref[2];
print "Center of Mass for Matrix Above\n";
printf("X:%.3f,Y:%.3f,Z:%.3f\n\n",$x,$y,$z);
my @tempMatrix = translateMatrixOperation($x,$y,$z,\@matrix);
-----------------------------------------
sub translateMatrixOperation
{
  my ($x, $y, $z, $translatematrix) = @_;
  my $arrsize = @$translatematrix;
  for(my $i = 0; $i < $arrsize; $i++)
  {
    for(my $j = 0; $j < $arrsize; $j++)
    {
        if ($j == 0)
        {
            $translatematrix->[$i][$j] -= $x;
        }
        elsif ($j == 1)
        {
           $translatematrix->[$i][$j] -= $y;
        }
        elsif ($j == 2)
        {
            $translatematrix->[$i][$j] -= $z;
        }
     }
  }

 return (\@translatematrix);

}

4

2 に答える 2

5

サブルーチンは、配列への参照を返します。結果を配列 @tempMatrix に格納しています。したがって、行列全体が に格納され$tempMatrix[0]ます。

それはおそらくあなたが望んでいたものではありません。サブルーチンが参照を返す場合は、スカラー変数を使用してそれを保持するか、結果を配列に代入する前に逆参照します。

my $array_ref = translateMatrixOperation($x,$y,$z,\@matrix);
my @array     = @{ translateMatrixOperation($x,$y,$z,\@matrix) };

後者のオプションは、配列をコピーする必要があるため、速度が遅くなり、メモリを集中的に使用します。

于 2013-08-14T09:08:03.277 に答える
0

配列を返すだけでなく、配列参照を返すという選択は、通常、サイズに帰着します。

小さな配列を転送する場合は、次のように記述します。

return @translatematrix;

大きな配列 (パフォーマンスに影響を与えるのに十分な大きさ) を転送している場合は、参照を返すことを検討する可能性があります。

それらはデカルト座標の配列のように見えるため、行列と呼ぶべきかどうかはよくわかりません。これは、熟考するのがはるかに簡単になります。


いずれにせよ、あなたのコードは非常に冗長で、間違っている可能性が高いです。

  • 必要がない場合は、ループに C スタイルを使用します。

    foreachループは一般に高速であり、ループの内容がより明確になります。

  • ほとんどの場合、正確に 3 つの値を変更しますが、内側の配列をループします。

  • 内側の for ループは、内側の配列ではなく、外側の配列の長さを使用します。

    外側のループの要素が 3 つ未満の場合、これは問題です。
    また、外側の配列が大きい場合、コードが何もせずにかなりの時間を費やしていることも意味します。

    これは、ループを使用するもう 1 つの理由でもあります。foreachループのテスト部分を間違えることはありません。

  • 元の配列の要素を変更します。

  • サブルーチンで実際には使用しなかった配列への参照を返します。

    コードに and がないか、コードの別の場所で宣言しているuse strict;としか思えません。use warnings;@translatematrix

元の配列を変更したバージョンを次に示します。(多分それはあなたが実際に望んでいたものです)

use strict;
use warnings;
my @matrix = ...;

# no need for a temporary variable
my ($x,$y,$z) = calculateCenterMass(@matrix);

print "Center of Mass for Matrix Above\n";
printf( "X:%.3f,Y:%.3f,Z:%.3f\n\n", $x, $y, $z );

# it returns a reference, not an array.
my $tempMatrix = translateMatrixOperation( $x, $y, $z, \@matrix );

sub translateMatrixOperation {
  my ($x, $y, $z, $translate_matrix) = @_;

  for my $xyz ( @$translate_matrix ){
    $xyz->[0] -= $x;
    $xyz->[1] -= $y;
    $xyz->[2] -= $z;
  }

  return @$translate_matrix if wantarray;
  return $translate_matrix;
}

これは、新しい配列を作成するバージョンです。

my $tempMatrix = translateMatrixOperation( $x, $y, $z, @matrix );

sub translateMatrixOperation {
  my ($x, $y, $z, @coord) = @_;

  # This is here in case you give it an array reference like you did before.
  # It is quite fragile, you should remove it if you don't need it.
  if( 1
    and @coord == 1
    and ref( my $aref = $coord[0] ) eq 'ARRAY'
    and ref($aref->[0]) eq 'ARRAY'
  ){
    @coord = @$aref;
  }


  # create a new list
  my @return = map{
    # of a new array refs based on the old ones
    [ $_->[0] - $x, $_->[1] - $y, $_->[2] - $z, @$_[3..$#$_] ]
    # the @$_[3..$#$_] part may be unnecessary
    # it should be removed if that is the case
  } @coord;

  return @return if wantarray;
  return \@return;
}

要らないと思う部分を削るとかなり短くなる

my $tempMatrix = translateMatrixOperation( $x, $y, $z, @matrix );

sub translateMatrixOperation {
  my ($x, $y, $z, @coords) = @_;

  my @return = map{
    [ $_->[0] - $x, $_->[1] - $y, $_->[2] - $z ]
  } @coords;

  return @return if wantarray;
  return \@return;
}

また、より適切な名前を考え出す必要がありますが、translateMatrixOperationあまり説明的ではありません。

于 2013-08-15T00:50:28.550 に答える