-2

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

4

3 回答 3

1

我从未使用过它,但看起来 Convert::BaseN 模块是一个不错的选择。 Convert::BaseN - base{2,4,8,16,32,64} 字符串的编码和解码

于 2012-09-20T20:44:34.163 回答
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
于 2012-09-20T21:07:25.183 回答
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 doubles 构建时为 26,使用 IEEE quads 构建时为 56。这将需要不同的实现。

比这更大的将需要一个诸如Math::BigInt之类的模块来让 Perl 存储它们。


更快更简单:

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);
}
于 2012-09-20T21:14:40.237 回答