循环变量

时间:2015-06-22 20:28:04

标签: perl scripting

我正在与perl合作制作一个可与Dot产品/各种矢量数学配合使用的脚本。我有一个工作脚本(仍在进行中/需要改进),这将完成我的要求。

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Math::Vector::Real;
use 5.010;
use Math::Trig;

my $source = "./IN";

my $out = "./OUT";

open(IN, '<', $source) or die "Couldn't open $source: $!\n";
open(OUT, '>', $out) or die "Couldn't open $out: $!\n";

my(@data);
while (<IN>) {
    push @data, [ split ];
}

my $v;
my $u;

$v = V(0, 0, 0); 
$u = V(0, 0, 0);

my $i = 0;

sub maths {
        my $dot = $v * $u;
        my $mag1 = (sqrt ((@$v[0])**2 + (@$v[1])**2 + (@$v[2])**2 ));
        my $mag2 = (sqrt ((@$u[0])**2 + (@$u[1])**2 + (@$u[2])**2 ));
        my $prefinal = acos( ( $dot ) / ( $mag1 * $mag2 ) );
        my $degrees = ( ( 180 / 3.14159 ) * ( $prefinal ) );
        return ($degrees);
}

my $ref1 = $data[$i][0];
my $ref2 = $data[$i][1];
my $ref3 = $data[$i][2];
my $ref4 = $data[$i+1][0];
my $ref5 = $data[$i+1][1];
my $ref6 = $data[$i+1][2];

$v->[0] = $ref1;
$v->[1] = $ref2;
$v->[2] = $ref3;

$u->[0] = $ref4;
$u->[1] = $ref5;
$u->[2] = $ref6;

my $result = maths;

print "$result\n";

脚本中的很多内容都是残留的,并且易于遵循(对我而言)。 我希望它做的是让脚本旋转输入文件的每一行并对其执行计算。 类似于拥有的东西:

foreach $i (@data) {

my $ref1 = $data[$i][0];
my $ref2 = $data[$i][1];
my $ref3 = $data[$i][2];
my $ref4 = $data[$i+1][0];
my $ref5 = $data[$i+1][1];
my $ref6 = $data[$i+1][2];

$v->[0] = $ref1;
$v->[1] = $ref2;
$v->[2] = $ref3;

$u->[0] = $ref4;
$u->[1] = $ref5;
$u->[2] = $ref6;

my $result = maths;

print "$result\n";
}

感激不尽。

2 个答案:

答案 0 :(得分:0)

您可以使用以下内容:

my $v = V( @{ $data[$i+0] } );
my $u = V( @{ $data[$i+1] } );

清理:

#!/usr/bin/perl

use strict;
use warnings;

use Math::Trig         qw( acos );
use Math::Vector::Real qw( V );

sub maths {
    my ($v, $u) = @_;
    my $dot = $v * $u;
    my $mag1 = sqrt( $v->[0]**2 + $v->[1]**2 + $v->[2]**2 );
    my $mag2 = sqrt( $u->[0]**2 + $u->[1]**2 + $u->[2]**2 );
    my $prefinal = acos( $dot / ( $mag1 * $mag2 ) );
    my $degrees = ( 180 / 3.14159 ) * $prefinal;
    return $degrees;
}

{
    my @data = map { V( split ) } <>;
    for my $i (0..$#data-1) {
        for my $j ($i+1..$#data) {
            my $maths = maths(@data[$i, $j]);
            print("$i,$j: $maths\n");
        }
    }
}

或者使用鲍罗丁的替代方法:

#!/usr/bin/perl

use strict;
use warnings;

use Math::Trig         qw( acos atan2 );
use Math::Vector::Real qw( V );

use constant DEG_PER_RAD => 45 / atan2(1, 1);

{
    my @data = map { V( split ) } <>;
    for my $i (0..$#data-1) {
        for my $j ($i+1..$#data) {
            my $maths = atan2(@data[$i, $j]) * DEG_PER_RAD;
            print("$i,$j: $maths\n");
        }
    }
}

用法:

perl script.pl ./IN >./OUT

答案 1 :(得分:0)

根据我的评论,您的程序的大多数功能都是由您已经使用的Math::Vector::Real模块提供的

看起来你想要文件中连续的3D矢量对之间的角度。此代码从文件中的每一行创建向量,直到@pair中有两个向量,然后使用atan2计算它们之间的角度。根据定义,DEG_PER_RAD根据atan2(1,1)的值π÷4 预先计算为

#!/usr/bin/perl

use strict;
use warnings;

use Math::Vector::Real;

use constant DEG_PER_RAD => 45 / atan2(1, 1);

my ( $source, $out ) = qw/ IN OUT /;

open my $in_fh,  '<', $source or die qq{Unable to open "$source" for input: $!\n};
open my $out_fh, '<', $out    or die qq{Unable to open "$out" for output: $!\n};
select $out_fh;

my @pair;

while ( <$in_fh> ) {

    push @pair, V(split);

    if ( @pair == 2 ) {
      my $degrees = atan2(@pair) * DEG_PER_RAD;
      print "$degrees\n";
      shift @pair;
    }
}

更新

要对每对可能的向量进行计算,最简单的方法是将整个文件读入一个向量数组,并使用两个嵌套循环从那里处理它们

此代码演示。在原始程序中select调用后插入它。它使用两个引起角度

的数组索引标记每行输出
my @data;
push @data, V(split) while <$in_fh>;

for my $i ( 0 .. $#data-1 ) {
    for my $j ( $i+1 .. $#data ) {
        my $degrees = atan2(@data[$i,$j]) * DEG_PER_RAD;
        print "[$i,$j] $degrees\n";
    }
}