5

我对 Perl 相对缺乏经验,但我的问题涉及在获取数值位时的解包函数。例如:

my $bits = unpack("b*", 1);
print $bits;

这将导致打印 10001100,即十进制的 140。在相反的顺序中,它是十进制的 49。我尝试过的任何其他值似乎都给出了不正确的位。

但是,当我通过 pack 运行 $bits 时,它再次产生 1。我在这里缺少什么吗?

当我认为我的问题已经解决时,我似乎得出了结论。也许我应该简要解释一下我正在尝试做什么。

我需要将一个可能长达 24 位(关键是它可能大于一个字节)的整数值转换为位串。这可以使用@ikegami 建议的解包和打包来完成,但我还需要找到一种方法将该位字符串转换回它的原始整数(不是它的字符串表示形式)。

正如我所提到的,我对 Perl 相对缺乏经验,而且我一直在尝试但没有成功。


我发现似乎是最佳解决方案:

my $bits = sprintf("%032b", $num);
print "$bits\n";
my $orig = unpack("N", pack("B32", substr("0" x 32 . $bits, -32)));
print "$orig\n";
4

6 回答 6

6

这可能很明显,但其他答案并没有明确指出:第二个参数 inunpack("b*", 1)被类型转换为 string "1",它的 ASCII 值为31in hex (最重要的半字节在前)。

相应的二进制文件是0011000110001100因为您使用"b*"的是"B*". 这些对应于二进制表示的相反“endian”形式。“字节序”只是最重要的位是在二进制表示的开头还是结尾。

于 2011-04-21T20:19:17.590 回答
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))
于 2011-04-21T20:12:37.057 回答
2

是 49。你必须想要类似的ord(1)东西sprintf("%064b", 1),尽管这看起来有点矫枉过正。

于 2011-04-21T20:12:26.303 回答
2

您正在尝试将整数转换为二进制然后返回。虽然您可以使用pack然后unpack做到这一点,但更好的方法是使用sprintfprintf%b格式:

my $int = 5;
my $bits = sprintf "%024b\n", $int;
print "$bits\n";

换一种方式(将 0 和 1 的字符串转换为整数),最好的方法是使用带前缀的oct函数:0b

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
于 2011-04-21T21:00:04.757 回答
1

你没有具体说明你的期望。我猜你在期待00000001

这是您提供的字节的正确位,至少在非 EBCDIC 系统上是这样。请记住,unpack 的输入是一个字符串(主要是字节串)。也许你想要

unpack('b*', pack('C', 1))

更新:正如其他人指出的那样,上面给出了10000000. 对于00000001,你会使用

unpack('B*', pack('C', 1))  # 00000001
于 2011-04-21T20:12:26.557 回答
0

你想要“B”而不是“b”。

$ perl -E'say unpack "b*", "1"'
10001100

$ perl -E'say unpack "B*", "1"'
00110001

于 2011-04-21T20:20:18.100 回答