我想知道它是否是Perl中的Do not care符号(X).
我有一个50位二进制输入(实际上,我使用BigInt).如果输入与数据库中的数据匹配,我将返回一个预定义的值.
假设数据库中的数据是11001100100010110111110110101001000010110101111101.
如果输入是X1001100100010110111110110101001000010110101111101,我想认为它是一个匹配的情况,因为X可以是1或0.我知道一种方法在50个1位中分割50位并做出异常,但我更愿意处理50在一起.
test.pl(主要代码,看起来很乱,但操作很简单,读取数据库和输入文件,并返回一个输出文件,包括匹配情况的预定义值.由test.pl运行):
#!/usr/bin/perl use strict; #use warnings; use Math::BigInt; #use Math::Gauss ':all'; #use Math::Gauss; use 5.010; use List::Util qw(sum); my $Astrip="cmp_top.iop.sparc0.exu.rml."; my $Aj=0; my @Aoutput; my $At=0; my $Agen; my @Aitems; my @Aweights; my @Aitems_p; my @Aweights_p; my $Ap=0; my $Aselected_p = 0; my $Atotal_p; my $Arand_p; my $Alimit_p; my $Ai=0; my $Am=0; my $Ak=0; my $Atotal; my $Arand; my $Alimit; my $Aselected =0; my $Attemp=0; my $Ane=0; my $Asum=0; my $Al=0; my $Attest=0; #### change edb workload - matmul open(CSV,'database.db')||die("Cannot open edb file $!"); my @Aedb; while(){ my @Arow=split(/\t/,$_); push(@Aedb,\@Arow); } close CSV || die $!; # if ($At == 0) { goto ASTART; } my @Ainput=do{ open my $Afh,"<","test.input" or die("Cannot open an input file $!"); <$Afh>; }; for (my $An=0; $An < (scalar @Ainput); $An +=3) { ### First loop $Attest = 0; for ($Ai=0; $Ai < (scalar @Aedb); $Ai +=2) { $a = Math::BigInt->new("$Aedb[$Ai][1]"); $b = Math::BigInt->new("$Ainput[$An]"); if ( $a == $b ) { $a = Math::BigInt->new("$Aedb[$Ai+1][1]"); $b = Math::BigInt->new("$Ainput[$An+1]"); if ( $a == $b ) { $Attemp=0; $Attest++; $Agen=$Ainput[$An+2]; if (not defined $Agen) { $Arand_p = rand();} else { $Arand_p = $Agen; } #$Attemp=0; for ($Aj=2; $Aj < scalar @{ $Aedb[$Ai+1] }; $Aj++) { if ( $Aedb[$Ai+1][$Aj]/$Aedb[$Ai+1][2] > $Arand_p ) { $At++; $Aedb[$Ai][$Aj] =~ s/\n//g; $Aoutput[$At+$An/3]= $Astrip.$Aedb[$Ai][$Aj]; $Attemp++; } } #$Aoutput[$An/3+$At-$Attemp]= $Attemp; } } } } open(my $Afh2, '>', 'test.output'); print $Afh2 join("\n", @Aoutput); close $Afh2;
database.db(数据库文件):
0.1 11001100100010110111110110101001000010110101111101 rml_irf_old_e_cwp_e[1] rml_irf_new_e_cwp_e[1] rml_irf_swap_even_e rml_irf_old_e_cwp_e[0] rml_irf_new_e_cwp_e[0] rml_irf_swap_odd_e 0.1 11101100110010011011001101100111001001100000010011 3.923510310023e-06 3.19470818154393e-08 7.05437377900141e-10 7.05437377900141e-10 4.89200539851702e-17 5.01433479478681e-19 0.1 10000110001111010010111101110011001001011110000100 rml_irf_new_e_cwp_e[1] rml_irf_new_e_cwp_e[0] 0.1 01110111010010000000101001000001100011011100011111 0.052908822741908 2.7185508579738e-05 0.1 01001100100100001011101000011111100101111011000111 rml_irf_new_e_cwp_e[1] 0.1 00111101000100001101010111010100000111100100100101 1.09213787524617e-25 0.1 00001000011110000101010110111000000111011110011001 rml_irf_new_e_cwp_e[1] rml_irf_new_lo_cwp_e[1] rml_irf_new_lo_cwp_e[2] 0.1 01101001011110101011111011011011101100110100000101 2.28019753307221e-06 2.89026436307201e-14 2.89026436307201e-14
test.input:
11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011
test.output(输入的预定义值,不匹配的情况下没有任何内容.我希望与X10011具有相同的输出...):
cmp_top.iop.sparc0.exu.rml.rml_irf_old_e_cwp_e[1]
任何帮助表示赞赏.
使用Math :: BigInt :(附带Perl)
use Math::BigInt qw( ); my $pattern = 'X1001100100010110111110110101001000010110101111101'; my $mask = Math::BigInt->from_bin( $pattern =~ tr/X01/011/r ); my $targ = Math::BigInt->from_bin( $pattern =~ tr/X/0/r ); for my $num_bin (qw( 11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011 )) { my $num = Math::BigInt->from_bin($num); if (($num & $mask) == $targ) { say "$num_bin matches"; } else { say "$num_bin doesn't match"; } }
使用Math :: UInt64 :(比BigInt快)
use Math::UInt64 qw( net_to_uint64 ); sub bin_to_uint64 { net_to_uint64 pack 'B*', substr( ( "0" x 64 ) . $_[0], -64 ) } my $pattern = 'X1001100100010110111110110101001000010110101111101'; my $mask = bin_to_uint64( $pattern =~ tr/X01/011/r ); my $targ = bin_to_uint64( $pattern =~ tr/X/0/r ); for my $num_bin (qw( 11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011 )) { my $num = bin_to_uint64($num); if (($num & $mask) == $targ) { say "$num_bin matches"; } else { say "$num_bin doesn't match"; } }
使用原生整数:(如果支持则最快)
use Config qw( %Config ); sub bin_to_uint64 { unpack 'Q>', pack 'B*', substr( ( '0' x 64 ) . $_[0], -64 ) } die("64-ints required\n") if $Config{ivsize} < 8; my $pattern = 'X1001100100010110111110110101001000010110101111101'; my $mask = bin_to_uint64( $pattern =~ tr/X01/011/r ); my $targ = bin_to_uint64( $pattern =~ tr/X/0/r ); for my $num_bin (qw( 11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011 )) { my $num = bin_to_uint64($num); if (($num & $mask) == $targ) { say "$num_bin matches"; } else { say "$num_bin doesn't match"; } }
使用压缩的int :(最快的.如上所述,假设pattern和num_bin的长度相同.)
sub bin_to_packed { pack 'B*', $_[0] } my $pattern = 'X1001100100010110111110110101001000010110101111101'; my $mask = bin_to_packed( $pattern =~ tr/X01/011/r ); my $targ = bin_to_packed( $pattern =~ tr/X/0/r ); for my $num_bin (qw( 11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011 )) { my $num = bin_to_packed($num); if (($num & $mask) eq $targ) { say "$num_bin matches"; } else { say "$num_bin doesn't match"; } }
使用字符串:(最快,因为在循环中不需要进行任何操作但实际检查.假设pattern和num_bin的长度相同.)
my $pattern = 'X1001100100010110111110110101001000010110101111101'; my $mask = $pattern =~ tr/X01/\x00\xFF\xFF/r; my $targ = $pattern =~ tr/X/\x00/r; for my $num_bin (qw( 11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011 )) { if (($num_bin & $mask) eq $targ) { say "$num_bin matches"; } else { say "$num_bin doesn't match"; } }
与上面相同,但没有5.14+
my $pattern = 'X1001100100010110111110110101001000010110101111101'; ( my $mask = $pattern ) =~ tr/X01/\x00\xFF\xFF/; ( my $targ = $pattern ) =~ tr/X/\x00/; for my $num_bin (qw( 11001100100010110111110110101001000010110101111101 11101100110010011011001101100111001001100000010011 )) { if (($num_bin & $mask) eq $targ) { say "$num_bin matches"; } else { say "$num_bin doesn't match"; } }
输出:
11001100100010110111110110101001000010110101111101 matches 11101100110010011011001101100111001001100000010011 doesn't match