你能解释一下我从解包中得到的信息吗?
我对 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";
I'm relatively inexperienced with Perl, but my question concerns the unpack function when getting the bits for a numeric value. For example:
my $bits = unpack("b*", 1);
print $bits;
This results in 10001100 being printed, which is 140 in decimal. In the reverse order it's 49 in decimal. Any other values I've tried seem to give the incorrect bits.
However, when I run $bits through pack, it produces 1 again. Is there something I'm missing here?
It seems that I jumped to conclusions when I thought my problem was solved. Maybe I should briefly explain what it is I'm trying do.
I need to convert an integer value that could be as big as 24 bits long (the point being that it could be bigger than one byte) into a bit string. This much can be accomplished using unpack and pack as suggested by @ikegami, but I also need to find a way to convert that bit string back into it's original integer (not a string representation of it).
As I mentioned, I'm relatively inexperienced with Perl, and I've been trying with no success.
I found what seems to be an optimal solution:
my $bits = sprintf("%032b", $num);
print "$bits\n";
my $orig = unpack("N", pack("B32", substr("0" x 32 . $bits, -32)));
print "$orig\n";
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这可能是显而易见的,但其他答案没有明确指出:
unpack("b*", 1)
中的第二个参数被类型转换为字符串"1"< /code>,其十六进制 ASCII 值为
31
(最高有效半字节在前)。相应的二进制文件为
00110001
,它在输出中反转为10001100
,因为您使用了"b*"
而不是"B *”
。它们对应于二进制表示的相反“字节序”形式。 “字节顺序”就是最高有效位是位于二进制表示的开头还是结尾。This might be obvious, but the other answers haven't pointed it out explicitly: The second argument in
unpack("b*", 1)
is being typecast to the string"1"
, which has an ASCII value of31
in hex (with the most significant nibble first).The corresponding binary would be
00110001
, which is reversed to10001100
in your output because you used"b*"
instead of"B*"
. These correspond to the opposite "endian" forms of the binary representation. "Endian-ness" is just whether the most-significant bits go at the start or the end of the binary representation.您没有具体说明您的期望。我猜您正在期待
00000001
。这是您提供的字节的正确位,至少在非 EBCDIC 系统上是这样。请记住,unpack 的输入是一个字符串(主要是字节字符串)。也许您想要
更新:正如其他人指出的那样,上面给出了
10000000
。对于00000001
,您可以使用You didn't specify what you expect. I'm guessing you're expecting
00000001
.That's the correct bits for the byte you provided, at least on non-EBCDIC systems. Remember, the input of unpack is a string (mostly strings of bytes). Perhaps you wanted
Update: As others have pointed out, the above gives
10000000
. For00000001
, you'd use是的,您错过了不同的机器支持不同的“endianness”。 Perl 将
1
视为'1'
(0x31)。所以,你看到的是 1 -> 1000(升序)和 3 -> 1100.“错误”取决于观点以及您是否为 Perl 提供了足够的信息来了解您想要的编码和字节顺序。
来自
pack
:我认为这就是你想要的:
Yes, you're missing that different machines support different "endianness". And Perl is treating
1
like'1'
so ( 0x31 ). So, you're seeing 1 -> 1000 (in ascending order) and 3 -> 1100."Wrong" depends on perspective and whether or not you gave Perl enough information to know what encoding and endianness you wanted.
From
pack
:I think this is what you want:
您正在尝试将整数转换为二进制,然后再转换回来。虽然您可以使用 pack 然后 解压,更好的方法是使用 sprintf 或 printf 以及
% b
格式:要采用另一种方式(将 0 和 1 的字符串转换为整数),最好的方法是使用 oct 函数带有
0b
前缀:正如其他人所解释的,
unpack
需要一个字符串来解包,因此如果您有一个整数,您首先必须将其pack
成一个字符串。%b
格式要求以整数开头。如果您需要在字节上执行大量操作,并且速度至关重要,您可以构建一个查找表:
You're trying to convert an integer to binary and then back. While you can do that with pack and then unpack, the better way is to use sprintf or printf with the
%b
format:To go the other way (converting a string of 0s & 1s to an integer), the best way is to use the oct function with a
0b
prefix:As the others explained,
unpack
expects a string to unpack, so if you have an integer, you first have topack
it into a string. The%b
format expects an integer to begin with.If you need to do a lot of this on bytes, and speed is crucial, you could build a lookup table:
ord(1)
是 49。您一定想要sprintf("%064b", 1)
之类的东西,尽管这看起来确实有点矫枉过正。The
ord(1)
is 49. You must want something likesprintf("%064b", 1)
, although that does seem like overkill.你想要“B”而不是“b”。
包
You want "B" instead of "b".
pack