Perl 中字符串最快的校验位例程是什么?
给定一串数字,我必须使用 Perl 尽快对所有数字求和。
我的第一个实现使用 unpack() 解压数字,然后使用 List::Utils 的 sum() 对数字列表求和。 它非常快,但是是否有更快的打包/解包方法来完成此任务?
我尝试了打包/解包组合,并对两种实现进行了基准测试。 使用的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 );
},
} );
Given a string of digits, I have to sum all digits as fast as possible using Perl.
My first implementation unpacks digits with unpack(), then sums the list of digits with List::Utils' sum().
It's pretty fast but is there a faster pack/unpack recipe for this task?
I tried with a pack/unpack combination, and benchmarked the two implementations.
Used CPU time is almost the same; maybe is there some fast trick I'm not aware of?
Here is how I did my benchmark:
#!/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 );
},
} );
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
unpack 不是分割字符串的最快方法:
产生:
因此,如果您必须将字符串分割为字符,那么
split
看起来是您的最佳选择。但反复对数字求和几乎与取数字 mod 9 相同(如米罗德指出)。不同之处在于
$Digits % 9
生成 0 而不是 9。解决该问题的一个公式是($Digits-1) % 9 + 1
,但是(在 Perl 中,至少)这不适用于全零情况(它产生 9 而不是 0)。 Perl 中有效的表达式是($Digits+0) && ($Digits % 9 || 9)
。第一项处理全零情况,第二项处理正常情况,第三项将 0 更改为 9。unpack isn't the fastest way to split a string:
Produces:
So
split
looks like your best bet if you have to split the string into characters.But repeatedly summing the digits is almost the same as taking the number mod 9 (as mirod pointed out). The difference is that
$Digits % 9
produces 0 instead of 9. One formula that fixes that is($Digits-1) % 9 + 1
, but (in Perl at least) that doesn't work for the all-zeros case (it produces 9 instead of 0). An expression that works in Perl is($Digits+0) && ($Digits % 9 || 9)
. The first term handles the all-zero case, the second the normal case, and the third changes 0 to 9.是否不要太聪明地使用打包/解包并使用简单的拆分,或者在数学上稍微聪明并使用模数,这比所有其他方法都好?
结果:
How about not being too clever with pack/unpack and using a simple split, or being mildly mathematically clever and using modulo, which beats the crap out of all the other methods?
Results: