распаковка не самый быстрый способ разбить строку:
#!/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);
},
} );
Производит:
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% --
Так что split
выглядит как ваш лучший выбор, если вам нужно разделитьстрока в символы.
Но многократное суммирование цифр равно почти так же, как взятие числа mod 9 (как указал мирод).Разница в том, что $Digits % 9
выдает 0 вместо 9. Одна формула, которая исправляет это ($Digits-1) % 9 + 1
, но (по крайней мере в Perl), которая не работает для случая со всеми нулями (она выдает 9 вместо 0).Выражение, которое работает в Perl: ($Digits+0) && ($Digits % 9 || 9)
.Первое слагаемое обрабатывает регистр с нулем, второе - с нормальным регистром, а третье - с 0 на 9.