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