Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 计算二进制文件中设置位数的最快方法是什么_Perl - Fatal编程技术网

Perl 计算二进制文件中设置位数的最快方法是什么

Perl 计算二进制文件中设置位数的最快方法是什么,perl,Perl,我想知道在Perl中计算二进制文件中设置位数(1)的最快方法是什么 我需要加快速度,因为我正在读取10个文件,每个文件大约有5000万位 我现在这样做太慢了,而且运行10-15个文件需要几个小时 我现在就是这样做的(我知道这很慢,效率很低,但在过去,文件要小得多,这种方法已经足够好了): 您可以执行循环,使字节一直向右移动(使用>运算符),并检查是否设置了最低位 大概是这样的: do { $counter++ if $bin_vec & 1; $bin_vec >>

我想知道在Perl中计算二进制文件中设置位数(1)的最快方法是什么 我需要加快速度,因为我正在读取10个文件,每个文件大约有5000万位

我现在这样做太慢了,而且运行10-15个文件需要几个小时

我现在就是这样做的(我知道这很慢,效率很低,但在过去,文件要小得多,这种方法已经足够好了):


您可以执行循环,使字节一直向右移动(使用
>
运算符),并检查是否设置了最低位

大概是这样的:

do {
   $counter++ if $bin_vec & 1;
   $bin_vec >> 1;
} while ($bin_vec > 0);

我可以想到两种方法: 1) 使用解包,因为你已经在做,但不要浪费周期做任何IO。 2) 使用具有给定字节中多少位的预计算值的查找表

1) 这里的诀窍是解包的“%”指令,它告诉解包对结果执行校验和,在二进制数据的情况下,它对所有0和1求和

use strict;
use warnings;

my $filename = $ARGV[0];

open(my $fh, '<', $filename) or die "$!";
binmode $fh;


my $count = 0;
my $word  = 0;

while ( read $fh, $word, 4 ) {
   $count += unpack '%32B*', $word;
}

print "filename contains $count set bits\n";
__END__
7733485
使用严格;
使用警告;
我的$filename=$ARGV[0];

open(我的$fh,'我太好奇了:你需要这些信息做什么?这是一种家庭作业吗?毕竟,我想不出一个更慢的版本来实现这一点:-pYou可以预计算一个哈希,其中包含从字节值(十进制)到设置位数的映射。(例如,5=>3)然后你读到的每个字节只需要执行一个表格查找。不,这不是家庭作业。我知道这是最慢的版本,但在过去,这些文件是20K-30K。所以我没有浪费时间搜索更快的文件:P。现在我需要它。这是否意味着这是一个秘密?我也非常好奇。^看起来像苏ch基本任务“数一数”然而,我无法想象在什么情况下我会需要它,除了一个或两个字节,人们会计算某种标志,但出于某种原因,不关心设置了哪些标志,只是数字……代码中有一个
count1
打字错误。还有,为什么要用
0
初始化
$word
/
$byte
速度?谢谢,我在同一个文件中编写了两个解决方案,使用了不同的计数器,忘记了更新那一个。我在这里测试了它们,结果是:--time./binary\u count\u 1.pl dummy\u 85Mbit.bin--Det count 8408334--1.112u 0.004s0:01.11 100.0%0+0k0+0io 0pf+0w--time./binary\u count\u 2.pl dummy\u 85Mbit.bin--Det count 8408334--3.104u 0。008s 0:03.11 99.6%0+0k 0+0io 0pf+0w——这意味着第一个版本更快。是的,可能是因为它一次读取4个字节,而不是1个。您可以将第二个版本修改为一次读取4个字节,然后将每个字节分别传递到查找表,它应该会加快很多可能优化的第二个版本:
my$count=0;而(sysread$fh,my$buf,64*1024){$count+=$bitcounts[$\]对于解包'C*',$buf;}
有一个比这个更有效的方法。
use strict;
use warnings;

my $filename = $ARGV[0];

open(my $fh, '<', $filename) or die "$!";
binmode $fh;


my $count = 0;
my $word  = 0;

while ( read $fh, $word, 4 ) {
   $count += unpack '%32B*', $word;
}

print "filename contains $count set bits\n";
__END__
7733485
use strict;
use warnings;

my $filename = $ARGV[0];

open(my $fh, '<', $filename) or die "$!";
binmode $fh;

my @bitcounts = (
   0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 
   3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 
   3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 
   2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 
   3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 
   5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 
   2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 
   4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
   3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 
   4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 
   5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 
   5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
);

my $count = 0;
my $byte  = 0;
while ( read $fh, $byte, 1 ) {
   $count += $bitcounts[ord($byte)];
}

print "filename contains $count set bits\n";
__END__
7733485