Perl中字符串的最快校验位例程是什么?

Mar*_*lis 3 perl unpack pack

给定一串数字,我必须使用Perl尽可能快地对所有数字求和.

我的第一个实现用unpack()解包数字,然后用List :: Utils的sum()对数字列表求和.它的速度非常快,但是这个任务有更快的打包/解包配方吗?

我试着使用pack/unpack组合,并对这两个实现进行了基准测试.二手CPU时间几乎相同; 也许有一些我不知道的快速技巧?

以下是我的基准测试方法:

#!/usr/bin/env perl

use 5.012;
use strict;
use List::Util qw/sum/;
use Benchmark qw/timethese/;

timethese ( 1000000, {
    list_util => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = sum( unpack( 'AAAAAAAAA', $CheckDigit ) );
        } while ( $CheckDigit > 9 );
    },
    perl_only => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = unpack( '%16S*', pack( 'S9', unpack( 'AAAAAAAAA', $CheckDigit ) ) );
        } while ( $CheckDigit > 9 );
    },
} );
Run Code Online (Sandbox Code Playgroud)

cjm*_*cjm 6

unpack不是拆分字符串的最快方法:

#!/usr/bin/env perl

use strict;
use List::Util qw/sum/;
use Benchmark qw/cmpthese/;

cmpthese ( -3, {
    list_util => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = sum( unpack( 'AAAAAAAAA', $CheckDigit ) );
        } while ( $CheckDigit > 9 );
    },
    unpack_star => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = sum( unpack( '(A)*', $CheckDigit ) );
        } while ( $CheckDigit > 9 );
    },
    re => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = sum( $CheckDigit =~ /(.)/g );
        } while ( $CheckDigit > 9 );
    },
    split => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = sum( split //, $CheckDigit );
        } while ( $CheckDigit > 9 );
    },
    perl_only => sub {
        my $CheckDigit = "999989989";
        do {
            $CheckDigit = unpack( '%16S*', pack( 'S9', unpack( 'AAAAAAAAA', $CheckDigit ) ) );
        } while ( $CheckDigit > 9 );
    },
    modulo => sub {
        my $CheckDigit = "999989989";
        $CheckDigit = ($CheckDigit+0) && ($CheckDigit % 9 || 9);
    },
} );
Run Code Online (Sandbox Code Playgroud)

生产:

                 Rate perl_only list_util       re unpack_star    split   modulo
perl_only     89882/s        --      -15%     -30%        -45%     -54%     -97%
list_util    105601/s       17%        --     -17%        -35%     -45%     -97%
re           127656/s       42%       21%       --        -21%     -34%     -96%
unpack_star  162308/s       81%       54%      27%          --     -16%     -95%
split        193405/s      115%       83%      52%         19%       --     -94%
modulo      3055254/s     3299%     2793%    2293%       1782%    1480%       --
Run Code Online (Sandbox Code Playgroud)

因此,split如果您必须将字符串拆分为字符,那么看起来是您最好的选择.

但重复求和的数字几乎与采用数字mod 9(如mirod指出)相同.不同之处在于$Digits % 9产生0而不是9.一个修复的公式($Digits-1) % 9 + 1,但是(至少在Perl中)不适用于全零情况(它产生9而不是0).在Perl中运行的表达式是($Digits+0) && ($Digits % 9 || 9).第一个术语处理全零情况,第二个术语处理正常情况,第三个术语处理0到9.