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

时间:2015-03-16 15:57:23

标签: 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. 任何人溢出以更好的方式使insertDecimal更有效率?
  2. 我怎么看都没有改进(74MM记录只好一分钟)?
  3. 如果Perl编译器重新调整第一个版本的代码以提高效率,那么我是否可以看到Perl选择的改进执行路径?

1 个答案:

答案 0 :(得分:2)

这两个例程看起来基本上都做了相同的工作:

  • 扫描$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%。在我的系统上,它将一个简单的例子减慢了1000%。