2017-01-13 16 views
1

Мне интересно, не символ ли в Perl символа (X).Мне не нужен символ в Perl

У меня есть 50-битный двоичный вход (на самом деле я использовал BigInt). Если вход согласован с данными в базе данных, я вернул бы предопределенное значение.

Предположим, что данные в базе данных 11001100100010110111110110101001000010110101111101.

Если вход X1001100100010110111110110101001000010110101111101, я хотел бы рассмотреть, что он соответствует случаю, потому что X может быть 1 или 0. Я знаю способ разделить 50 бит в 50 1 бит и сделать исключение, но я бы предпочитают обрабатывать 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(<CSV>){ 
    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 

тес t.output (предопределенное значение для ввода и ничего для непревзойденного случая. Я хотел бы иметь тот же результат с X10011 ...):

cmp_top.iop.sparc0.exu.rml.rml_irf_old_e_cwp_e[1] 

Любая помощь приветствуется.

+4

1) Вам не нужно 'BigInt' для 50 бит; 2) Вы можете просто заменить 'X' на' .' и проверить соответствие шаблона. –

+0

@Sinan Ünür, я уверен, что без BigInt он не будет работать, если вы хотите использовать побитовое число, а ваш IV размер - 32 бита. (Побитовое - И намного эффективнее, чем регулярное совпадение.) – ikegami

+0

@ikegami Если это так, два 32-битных целых числа по-прежнему будут быстрее, чем 'BigInt'. Я не входил во все пути, которые можно сделать без использования «BigInt». –

ответ

3
#!/usr/bin/env perl 

use strict; 
use warnings; 

my $search_for = 'X1001100100010110111110110101001000010110101111101'; 
(my $pat = $search_for) =~ s/X/./g; 

while (my $line = <DATA>) { 
    next unless $line =~ /\S/; 
    my $key = (split ' ', $line, 3)[1]; 
    if ($key =~ /^$pat\z/) { 
     print $line; 
    } 
} 

__DATA__ 
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- 

Кроме того, вы действительно должны критически взглянуть на свои переменные. У вас их слишком много, и их не называют полезными. Кроме того, если все начинается с A, A не передает информацию.

1

Если я правильно понял, вам нужны первые (наименее значимые) 49 бит, чтобы они были одинаковыми.

Например, установите бит 50 для обоих затем сравнить

if (($v1 | (1<<49)) == ($v2 | (1<<49))) { say "Match" } 

где $v1 и $v2 целые числа, которые могут отличаться только в 50-й бит для теста, чтобы вернуться верно.

Остальные о выборе способа формирования этих целых чисел из двоичных строк.


Использование Math::BigInt как в вопросе (с номерами сравнения ikegami «ы)

use warnings; 
use strict; 
use Math::BigInt; 

my $input_bin = '01001100100010110111110110101001000010110101111101'; 
my $input = Math::BigInt->from_bin($input_bin);  
print "$input_bin input\n"; 

# First number in @nums differs from input only in the left-most bit 
my @nums = (
    '11001100100010110111110110101001000010110101111101', 
    '11101100110010011011001101100111001001100000010011' 
); 

my $bits = 49; 
foreach my $num_bin (@nums) 
{ 
    my $num = Math::BigInt->from_bin($num_bin); 

    if (($input | (1<<$bits)) == ($num | (1<<$bits))) 
    { 
     print "$num_bin matches\n"; 
    } 
    else { 
     print "$num_bin does not match\n" 
    } 
} 

Печать

 
01001100100010110111110110101001000010110101111101 input 
11001100100010110111110110101001000010110101111101 matches 
11101100110010011011001101100111001001100000010011 does not match 

Существуют и другие модули для этого, во-первых, Math::Int64.

Если у вас нет другого использования Math::BigInt, вы можете получить целые числа другими способами, если ваша система поддерживает 64-битную поддержку, и с ней был скомпилирован Perl.


Используя pack, где строка первой необходимости дополняется до 64

my $input = unpack("Q>", pack("B*", substr("0" x 64 . $input_bin, -64))); 

где Q является

q A signed quad (64-bit) value. 
    Q An unsigned quad value. 
    (Quads are available only if your system supports 64-bit 
     integer values _and_ if Perl has been compiled to support 
     those. Raises an exception otherwise.) 

и > является большим обратным порядком байтов модификатора, необходимо по согласованию с B шаблон в pack.


Использование oct гораздо проще, если вы не возражаете, выключая 'portable' предупреждения

no warnings 'portable'; 

my $input = oct '0b' . $input_bin; 

my $bits = 49; 
foreach my $num_bin (@nums) 
{ 
    my $num = oct '0b' . $num_bin; 

    if (($input | (1<<$bits)) == ($num | (1<<$bits))) { 
     print "$num_bin matches\n"; 
    } else { 
     print "$num_bin does not match\n" 
    } 
} 

Предупреждение будет примерно такой код не является портативным между 32 и 64-битных Перлз. Это должно быть значительно быстрее, чем pack.

6

Использование 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"; 
    } 
} 

Использование собственных чисел: (Fastest но если поддерживается)

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"; 
    } 
} 

Использование упакованных ints: (Самый быстрый пока. Как указано, предполагается, что шаблон и num_bin равны t он такой же длины)

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"; 
    } 
} 

Использование строк:. (самый быстрый, потому что ничто не должно быть сделано в петле, но фактической проверки. Предполагает модели и 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 
+0

Благодарим вас за помощь. Я решил использовать строчную версию, потому что она самая быстрая. Кроме того, я сожалею о своем медленном ответе. Недавно я переехал в другое государство и получил новую работу, поэтому я не стал следить. Спасибо, в любом случае! –

0

Спасибо за все ваши ответы. Буду признателен за всю помощь. Я думаю, что я хотел знать, ответ Шинан. Я думаю, что символ «Не волнует» - это «.» поэтому я бы использовал "." вместо использования «X».

Кроме того, я думаю, что моего первого объяснения было недостаточно, поэтому я бы объяснил детали.

1) Любой бит ввода может быть неважным, даже если я использовал его только для первого бита в моем примере.

2) BigInt - Даже если этот пример 50-бит, я буду использовать больше бит позже, поэтому нативного целого недостаточно. Тем не менее, Math :: Uint64 намного быстрее, как предложил икегами, и я буду использовать его.

Я испытаю все ваши предложения сегодня вечером и отправлю свой ответ в ближайшее время. Еще раз спасибо.

+0

Это не ответ. – toolic

 Смежные вопросы

  • Нет связанных вопросов^_^