在perl字符串中有效地插入小数



我遇到了代码:

sub insertDecimal
{
        my $number = shift;
        my $sigDigRight = shift;
        if ($number =~ /./) { return ($number); }
        elsif (length $number < $sigDigRight) { return ($number); }
        else
        {
                my $leftSide = substr($number, 0, (length $number)-$sigDigRight);
                my $rightSide = substr($number, (length $number)-$sigDigRight, );
                return ($leftSide . "." . $rightSide);
        }
}

我希望改进/重写为:

sub insertDecimal
{
        my ($number, $sigDigRight) = @_;
        return $number if index ($number, '.') != -1 or length $number < $sigDigRight;
        # YES! substr takes an LVALUE ... perldoc it for more :)
        substr($number, -$sigDigRight, 0) = '.';
        return $number;
}

令我非常惊讶的是,一些 74 毫米唱片的运行在第二版中几乎没有任何改进。

问题:

  1. 有人会溢出更好的方法来使插入十进制更有效率吗?
  2. 为什么我根本没有看到任何改进(在 74MM 记录上只好了一分钟)?
  3. 如果Perl
  4. 编译器正在重新调整第一个版本的代码以提高效率,那么无论如何我可以看到Perl选择的改进的执行路径吗?

这两个例程似乎执行的工作量基本相同:

  • 扫描$number单个字符(任何编译器都应该能够将该正则表达式匹配减少到index

  • $number长度与限制进行比较

  • 可能会在$number某处插入单个字符

使用左值substr(或者,只是利用第四个参数来substr)可能会使插入更有效率,但毕竟,事情必须移动。

在我看来,优化的最大机会来自将长度检查移到小数点检查之前。

我很想重写你的例程

sub insertDecimal {
    my ($number, $sigDigRight) = @_;
    return $number if length($number) < $sigDigRight;
    return $number if index($number, '.') >= 0;
    substr($number, -$sigDigRight, 0, '.');
    $number;
}

我发现简单的决定和简短的线条更容易理解。我认为这不应该改变函数的正确性。

一个丑陋的选择是:

sub gah {
    my ($number, $sigDigRight) = @_;
    my $n = length($number) - $sigDigRight;
    return $number unless $n > 0;
    $number =~ s{A ([^.]{$n}) ([^.]+) z}{$1.$2}x;
    $number;
}

这将检查.与更换操作相结合。

同样,我不能确定这是正确的,但这是您需要探索的东西。

我可能不会选择gah,除非改进超过至少一个小时左右的 20%。在我的系统上,它将一个简单的示例减慢了 1,000%。

最新更新