我对Perl相对缺乏经验,但我的问题是在获取数值的位时解压缩函数。例如:
my $bits = unpack("b*", 1);
print $bits;
这导致打印10001100,十进制140。按相反的顺序,它是十进制的49。我试过的任何其他值似乎都给出了不正确的位。
然而,当我通过pack运行$ bits时,它再次产生1。这里有什么我想念的吗?
当我认为我的问题得到解决时,似乎我得出了结论。也许我应该简要解释一下我正在尝试做什么。
我需要将一个可能大到24位长的整数值(可能大于一个字节)转换为位串。这可以使用@ikegami建议的unpack和pack来完成,但是我还需要找到一种方法将该位字符串转换回它的原始整数(不是它的字符串表示)。
正如我所提到的,我对Perl相对缺乏经验,而且我一直在尝试没有成功。
我发现了什么似乎是最佳解决方案:
my $bits = sprintf("%032b", $num);
print "$bits\n";
my $orig = unpack("N", pack("B32", substr("0" x 32 . $bits, -32)));
print "$orig\n";
答案 0 :(得分:6)
这可能是显而易见的,但其他答案没有明确指出:unpack("b*", 1)
中的第二个参数是字符串"1"
的类型转换,其ASCII值为{{1在十六进制中(首先是最重要的半字节)。
相应的二进制文件为31
,由于您使用的是00110001
而不是10001100
,因此会在输出中反转为"b*"
。这些对应于二进制表示的相反“endian”形式。 “Endian-ness”只是最重要的位是在二进制表示的开头还是结尾。
答案 1 :(得分:3)
是的,您错过了不同的计算机支持不同的"endianness"。并且Perl正在1
处理'1'
所以(0x31)。所以,你看到1 - > 1000(按升序排列)和3 - > 1100。
“错误”取决于视角以及您是否给Perl足够的信息来了解您想要的编码和字节顺序。
来自pack
:
b A bit string (ascending bit order inside each byte, like vec()).
B A bit string (descending bit order inside each byte).
我认为这就是你想要的:
unpack( 'B*', chr(1))
答案 2 :(得分:2)
ord(1)
是49.你必须要sprintf("%064b", 1)
这样的东西,虽然这看起来有点矫枉过正。
答案 3 :(得分:2)
您正在尝试将整数转换为二进制,然后返回。虽然您可以使用pack然后unpack执行此操作,但更好的方法是使用sprintf或printf %b
格式:
my $int = 5;
my $bits = sprintf "%024b\n", $int;
print "$bits\n";
要采用另一种方式(将0和1的字符串转换为整数),最好的方法是使用带有0b
前缀的oct函数:
my $orig = oct("0b$bits");
print "$orig\n";
正如其他人所解释的那样,unpack
需要一个字符串来解包,所以如果你有一个整数,你首先必须将它pack
变成一个字符串。 %b
格式需要以整数开头。
如果你需要在字节上做很多事情,速度至关重要,你可以建立一个查找表:
my @binary = map { sprintf '%08b', $_ } 0 .. 255;
print $binary[$int]; # Assuming $int is between 0 and 255
答案 4 :(得分:1)
您没有指定您的期望。我猜你在期待00000001
。
这是您提供的字节的正确位,至少在非EBCDIC系统上是这样。请记住,unpack的输入是一个字符串(主要是字节串)。也许你想要
unpack('b*', pack('C', 1))
更新:正如其他人所指出的那样,上面给出了10000000
。对于00000001
,您可以使用
unpack('B*', pack('C', 1)) # 00000001
答案 5 :(得分:0)
你想要“B”而不是“b”。
$ perl -E'say unpack "b*", "1"'
10001100
$ perl -E'say unpack "B*", "1"'
00110001