perl从四元组快速切换到十进制

时间:2012-09-20 20:30:17

标签: perl pack unpack

我将核苷酸A,C,G,T表示为0,1,2,3,之后我需要将表示为四元的序列转换为十进制。有没有办法在Perl中实现这一目标?我不确定打包/解包是否可以这样做。

3 个答案:

答案 0 :(得分:1)

我从未使用它,但看起来Convert :: BaseN模块将是一个不错的选择。 Convert::BaseN - encoding and decoding of base{2,4,8,16,32,64} strings

答案 1 :(得分:1)

通过处理循环中的每个数字,将base-4字符串计算为十进制非常简单

请注意,在32位计算机上,您将无法表示超过16个碱基的序列

此代码显示了这个想法

use strict;
use warnings;

print seq2dec('ACGTACGTACGTACGT');

sub seq2dec{
  my ($sequence) = @_;
  my $n = 0;
  for (map {index 'ACGT', $_} split //, $sequence) {
    $n = $n * 4 + $_;
  }
  return $n;
}

<强>输出

454761243

答案 2 :(得分:1)

Base 4只需2位,因此很容易有效处理。

my $uvsize = length(pack('J>', 0)) * 8;
my %base4to2 = map { $_ => sprintf('%2b', $_) } 0..3;

sub base4to10 {
   my ($s) = @_;
   $s =~ s/(.)/$base4to2{$1}/sg;
   $s = substr(("0" x $uvsize) . $s, -$uvsize);
   return unpack('J>', pack('B*', $s));
}

这允许在支持32位整数的构建上输入16位,在支持64位整数的构建上输入32位。

使用浮点可以支持略大的数字:使用IEEE双打构建26,使用IEEE四元组构建56。这需要不同的实现。

大于此要求Perl的Math::BigInt等模块存储它们。


更快更简单:

my %base4to16 = (
   '0' => '0',   '00' => '0',   '20' => '8',
   '1' => '1',   '01' => '1',   '21' => '9',
   '2' => '2',   '02' => '2',   '22' => 'A',
   '3' => '3',   '03' => '3',   '23' => 'B',
                 '10' => '4',   '30' => 'C',
                 '11' => '5',   '31' => 'D',
                 '12' => '6',   '32' => 'E',
                 '13' => '7',   '33' => 'F',
);

sub base4to10 {
   (my $s = $_[0]) =~ s/(..?)/$base4to16{$1}/sg;
   return hex($s);
}