0

目前我正在学习 Perl 和 gnuplot。我想知道如何根据下一个值计算某个值。例如,我有一个文本文件包括:

#ID(X) Y
1 1
3 9
5 11

输出也应该显示未知 ID 的值。所以,输出应该显示:

#ID(X) Y
1 1
2 5
3 9
4 10
5 11

ID#2 的 Y 基于以下公式:((2-3)/(1-3))*1 + ((2-1)/(3-1))*9,即线性代数

Y2=((X2-X3)/(X1-X3))*Y1 + ((X2-X1)/(X3-X1)) * Y3

ID#5 也是如此

目前我有这个代码,

    #! /usr/bin/perl -w
    use strict;

    my $prev_id = 0;
    my $prev_val = 0;
    my $next_id;
    my $next_val;

    while (<>)
    {
    my ($id, $val) = split;
    for (my $i = $prev_id + 1; $i < $next_id; $i++)
    {
    $val = (($id - $next_id) / ($prev_id - $next_id)) * $prev_val + (($id - $prev_id) / ($next_id - $prev_id)) * $next_val;
    printf ("%d %s\n", $i, $val);
    }
    printf ("%d %s\n", $id, $val);
    ($prev_val, $prev_id) = ($val, $id);
    ($next_val, $next_id) = ($prev_val, $prev_id);  
}
4

4 回答 4

1

鉴于您总是处理 1 的整数间距,您的公式似乎比我预期的要复杂。

您没有说是否要填补多个连续缺失值的空白,但让我们假设您想要。

您所做的是在第一行中读取,并说这是当前行,然后将其输出。现在你阅读下一行,如果它的 ID 不是预期的,你用简单的线性插值来填补空白......

伪代码

(currID, currY) = readline()
outputvals( currID, currY )

while lines remain do
    (nextID, nextY) = readline()
    gap = nextID - currID

    for i = 1 to gap
        id = currID + i
        y = currY + (nextY - currY) * i / gap
        outputvals( id, y )
    end

    (currID, currY) = (nextID, nextY)
end

对不起,非 Perl 代码。只是我好久没用Perl了,一半的语法记不住了。=) 这里的概念很容易转化为代码。

于 2013-01-16T03:52:15.243 回答
0

使用数组可能是要走的路。这也将使您的数据可用于进一步操作。

** 警告:不适用于 y 的多个连续缺失值;请参阅@paddy 的回答。

#!/usr/bin/perl
use strict;
use warnings;

my @coordinates;
while (<DATA>) {
    my ($x, $y) = split;
    $coordinates[$x] = $y;
}

# note that the for loop starts on index 1 here ...
for my $x (1 .. $#coordinates) {
    if (! $coordinates[$x]) {
        $coordinates[$x] = (($x - ($x + 1)) / (($x - 1) - ($x + 1)))
                         * $coordinates[$x - 1]
                         + (($x - ($x - 1)) / (($x + 1) - ($x - 1)))
                         * $coordinates[$x + 1];
    }

    print "$x - $coordinates[$x]\n";
}

__DATA__
1 1
3 9
5 11
于 2013-01-16T21:14:21.360 回答
0

您表示您的问题是获得下一个值。关键不是向前看,而是向后看。

my $prev = get first value;
my ($prev_a, $prev_b) = parse($prev);

my $this = get second value;
my ($this_a, $this_b) = parse($this);

while ($next = get next value) {
   my ($next_a, $next_b) = parse($next);
   ...
   $prev = $this;  $prev_a = $this_a;  $prev_b = $this_b;  
   $this = $next;  $this_a = $next_a;  $this_b = $next_b;
}
于 2013-01-16T06:25:59.513 回答
-1
#! /usr/bin/perl -w
use strict;

my @in = (1,9,11);
my @out;

for (my $i = 0; $i<$#in; $i++) {

    my $j = $i*2;

    my $X1 = $i;
    my $X2 = $i+1;
    my $X3 = $i+2;

    my $Y1 = $in[$i];
    my $Y3 = $in[$i+1];

    my $Y2 = $Y1*(($X2-$X3)/($X1-$X3))
           + $Y3*(($X2-$X1)/($X3-$X1));

    $out[$j]   = $in[$i];
    $out[$j+1] = $Y2;
}

$out[$#in*2] = $in[$#in];
print (join " ",@out);
于 2013-01-16T04:11:12.097 回答