Perl进制之间的转换示例
2013-08-15 14:59:34 阿炯

Perl支持多种格式的数据格式和进制,它们之间的转换也是十分方便的。二进制(Binary)、八进制(Octal)、十进制(Decimal)、十六进制(Hexadecimal)等,当然最常用的函数还是内置的'sprintf'了。


再开始介绍转换函数前,先来看看进制间的一些转换算法。

2、8、16转十进制公式:
abcde = e * 1 + d * 2 + c * 2^2 + a * 2^3
abcde = e * 1 + d * 8 + c * 8^2 + a * 8^3
abcde = e * 1 + d * 16 + c * 16^2 + a * 16^3

示例
# binary --> decimal
100101 = 1 * 1 + 1 * 2^2 + 1 * 2^5 = 1 + 4 + 32 = 37

# oct --> decimal
123 = 3 * 1 + 2 * 8 + 1 * 8^2 =3 + 16 + 64 = 83

# hex --> decimal
0xa0c3 = 3 * 1 + 12 * 16 + 10 * 16^3 = 3 + 192 + 40960 = 41155

十进制转其它进制

公式1:将十进制数不断除以进制位数,直到无法再除时,最后得到的商以及每步得到的余数组合起来就是对应进制数的值。

公式2:用进制数的幂次方不断累加测试,主要用于十进制转2进制,偶尔用于十进制转8进制,几乎不用于10进制转16进制。

例如,123转2进制:
          商    余
123 / 2 = 61 -> 1
61  / 2 = 30 -> 1
30  / 2 = 15 -> 0
15  / 2 = 7  -> 1
7   / 2 = 3  -> 1
3   / 2 = 1  -> 1

其中最后一步的商为1,从后向前每步余数为111011,组合的结果是1111011,这就是123对应的2进制值。

累加法:
123 = 64  + 32 + 16 + 8 + 2 + 1
        2^6   2^5  2^4  2^3 2^1 2^0

所以,123的二进制值为1111011。

10进制的123转8进制:
          商    余
123 / 8 = 15 -> 3
15  / 8  = 1 -> 7

所以123对应的8进制数为173。

二进制转八进制

公式:二进制数从最右开始,每3位一组计算十进制数,组合结果就是对应的八进制数值。
111001011   ->   ?
111 001 011
 ↓   ↓   ↓
 7   1   3  -> 713

所以结果是0713。

二进制转十六进制

公式:二进制数从最右开始,每4位一组计算十进制数,组合结果就是对应的十六进制数值。
111001011   ->   ?
1 1100 1011
↓   ↓   ↓
1  12  11   -> 1CB

所以结果是0x1cb。

八和十六进制转二进制


公式:将每一位转换成3位或4位的二进制,组合起来的结果就是对应的二进制值。

# 八进制的123转二进制
123
3 -> 011
2 -> 010
1 -> 001

所以8进制的123转二进制的结果是1010011。

# 十六进制的123转二进制
123
3 -> 0011
2 -> 0010
1 -> 0001

所以8进制的123转二进制的结果是100100011。


Dec to Hex(十进制转十六进制)

Use function sprintf("%x", DECNUMBER) or sprintf("%X", DECNUMBER) for hexadecimal numbers with capital letters.
$decvalue=200;
$hexvalue=sprintf("%x", $decvalue);  ## gives c8
$hexvalue=sprintf("%X", $decvalue);  ## gives C8

#从$nval数字中剥离连续的16进制数字,从而将该数字转换为16进制数字
use integer;
my ($nval,@digits) = (258);
print "$nval in hex = ";

while($nval) {
    push @digits, (0 .. 9, 'a' .. 'f')[$nval & 15];
    $nval /= 16;
}
while(@digits){
    print pop @digits;
}


Dec to Oct(十进制转八进制)

Use sprintf("%o", DECNUMBER)
$decvalue=200;
$octval=sprintf("%o", $decvalue);

将会输出:
317

使用'0'做为前导 **sprintf("%#o", DECNUMBER);
$decvalue=200;
$octval=sprintf("%#o", $decvalue);

将会有如下的输出:
0317

Dec to Bin(十进制转二进制)


使用sprintf("%b", DECNUMBER)
$decvalue=200;
$binvalue=sprintf("%b", $decvalue);

Hex to Dec(十六进制转十进制)

一般使用函数:hex( HEXNUMBER)
十六进制数的大小写所转换的结果都是一样的。

$hexvalue='FC';
$decvalue= hex($hexvalue);
$hexvalue='fc';
$decvalue= hex($hexvalue);
$hexvalue='0xfc';
$decvalue= hex($hexvalue);

Hex to Oct(十六进制转八进制)

sprintf("%o", hex( HEXNUMBER))
sprintf("%#o", hex( HEXNUMBER))

$hexvalue="fcff";
$octvalue=sprintf("%o", hex( $hexvalue));

Hex to Bin(十六进制转二进制)

sprintf("%b", hex(HEXNUMBER))

$hexvalue="fc";
$binvalue=sprintf("%b", hex($hexvalue));

Oct to Hex(八进制转十六进制)

sprintf("%x", oct(OCTNUMBER))
sprintf("%X", oct(OCTNUMBER))
两个函数的区别是:输出的字符大小写不一样。

$octvalue="0176377";
$hexvalue=sprintf("%x", oct($octvalue));

Oct to Dec(八进制转十进制)

oct(OCTNUMBER)

$octvalue="0176377";
$decvalue=oct($octvalue);

Oct to Bin(八进制转二进制)

sprintf("%b", oct(OCTNUMBER))

$octvalue="0176377";
$binvalue=sprintf("%b", oct( $octvalue));

Bin to Hex(二进制转十六进制)

Use a combination of functions remember to put in 0b before the binary number.需要在二进制数前加'0b',然后调用'oct'进行转换。
sprintf("%x", oct("0bOCTNUMBER"))
sprintf("%X", oct("0bOCTNUMBER"))

$binvalue="11001111";
$hexvalue=sprintf("%x", oct("0b$binvalue"));
$hexvalue=sprintf("%X", oct("0b$binvalue"));

Bin to Dec(二进制转十进制)

Use function oct and insert 0b before the binary number.需要在二进制数前加'0b',然后调用'oct'进行转换。

$binvalue="11001111";
$decvalue=oct("0b$binvalue");

Bin to Oct(二进制转八进制)

$binvalue="11001111";
$octvalue=sprintf("%o", oct("0b$binvalue"));
$octvalue=sprintf("%#o", oct("0b$binvalue"));#Generates octal number with leading zero

十进制转二进制一例

在脚本程序中以指定的位宽显示

1.使用字串连接的方式
"%".$width."b"
join('', "%", $width, "b")

2.变量内插
"%${width}b"

3.sprintf
sprintf 接受*作为变量中要提供的值的占位符。
sprintf("%*b", $width, $num)

如果需要前导以0填充而不是前导空格,只需在%后添加一个0即可。

use v5.20;
my $width=5;

for my $i (0..31){
    printf "%*b\n",$width,$i;
}
say '#' x 16;
for my $i (0..31){
    printf "%${width}b\n",$i;
}
say '#' x 16;
for my $i (0..31){
    say sprintf("%0${width}b",$i);
}



参考链接:
Convert Hex-Dec-Oct-Bin

print系列函数使用参考

Base64