简体   繁体   English

Python输出奇怪的bytearray

[英]Python outputs strange bytearray

Python sometimes generates strange cryptic byte arrays. Python有时会产生奇怪的神秘字节数组。 I have no clue how to interpret them. 我不知道如何解释它们。

Consider the following example. 请考虑以下示例。

import struct
floats = [3.14, 2.7, 0.0, -1.0, 1.1]
s = struct.pack('f'*len(floats), *floats)
print("The bytes:")
print(s)

The struct.pack function should output the 'bytes-representation' of each value in the list. struct.pack函数应该输出列表中每个值的'bytes-representation'。 The list consists of 64-bit floating point numbers (my computer is 64-bit), so I would expect every float to be represented by 8 bytes: 该列表由64位浮点数组成(我的计算机是64位),所以我希望每个浮点数由8个字节表示:

 3.14 -> 0x40 0x09 0x1E 0xB8 0x51 0xEB 0x85 0x1F
 2.7  -> 0x40 0x05 0x99 0x99 0x99 0x99 0x99 0x9A
 0.0  -> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-1.0  -> 0xBF 0xF0 0x00 0x00 0x00 0x00 0x00 0x00
 1.1  -> 0x3F 0xF1 0x99 0x99 0x99 0x99 0x99 0x9A

By the way, I have used the following website to make the proper conversion: http://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html 顺便说一下,我使用以下网站进行了正确的转换: http//babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html

Unfortunately, Python does not output those bytes I would expect. 不幸的是,Python没有输出我期望的那些字节。 Instead, Python outputs some very cryptic list of bytes. 相反,Python会输出一些非常神秘的字节列表。 But is this really a list of bytes? 但这真的是一个字节列表吗? The thing that Python outputs is so strange: Python输出的东西很奇怪:

b'\xc3\xf5H@\xcd\xcc,@\x00\x00\x00\x00\x00\x00\x80\xbf\xcd\xcc\x8c?'

Please help me to understand what Python is doing here. 请帮助我理解Python在这里做了什么。

EDIT 编辑

Apparently I should use 'd' instead of 'f' , since I'm using double precision floating point numbers on my machine. 显然我应该使用'd'而不是'f' ,因为我在我的机器上使用双精度浮点数。 Thank you mr. 谢谢先生。 Rad Lexus for your answer. Rad雷克萨斯为您的答案。 But I'm still a bit puzzled about the Python outputs. 但我仍然对Python输出感到有些困惑。 Let me clarify. 让我澄清一下。

I start with the following code that you gave me: 我从您给我的以下代码开始:

import struct
floats = [3.14, 2.7, 0.0, -1.0, 1.1]
s = []
for f in floats:
    s.append(struct.pack('d', f))

Before proceeding, I inspect the object s to get a grasp of what is happening. 在开始之前,我检查对象s来获得所发生的事情的把握。 This is what I get from s : 这是我从s得到s

>>> s
[ b'\x1f\x85\xebQ\xb8\x1e\t@', 
  b'\x9a\x99\x99\x99\x99\x99\x05@',
  b'\x00\x00\x00\x00\x00\x00\x00\x00', 
  b'\x00\x00\x00\x00\x00\x00\xf0\xbf',
  b'\x9a\x99\x99\x99\x99\x99\xf1?'     ]

Some entries in s are 8 bytes long. s中的一些条目长度为8个字节。 That is what I would expect. 这就是我所期待的。 But some entries are shorter. 但有些参赛作品更短。 Anyway, there is no entry that gives the correct 8-byte representation of the corresponding float number - except for the float 0.0 . 无论如何,没有任何条目,得到相应的浮点数的正确8字节表示-除了浮子0.0

Your code continues with some magic to extract the actual correct 8 bytes per float: 您的代码继续使用一些魔法来提取每个浮点数实际正确的8个字节:

print("The bytes:")
for floatInHex in s:
    for byteval in floatInHex:
        print ('%02x' % byteval, end="")

Now we get the correct result. 现在我们得到了正确的结果。 But why is the s object not yet containing the correct 8-bytes per float, to begin with? 但是为什么s对象还没有包含每个浮点数正确的8字节,首先? Why is this extra magic needed? 为什么需要这种额外的魔力?


>>> binascii.hexlify(struct.pack('>d', floats[0]))
b'40091eb851eb851f'

>>> import struct
>>> import binascii
>>>
>>> floats = [3.14, 2.7, 0.0, -1.0, 1.1]
>>> s = struct.pack('>' + 'd'*len(floats), *floats)
>>> binascii.hexlify(s)
b'40091eb851eb851f400599999999999a0000000000000000bff00000000000003ff199999999999a'

If you want to get each float representation separately, you need to iterate them and conver them. 如果要分别获取每个浮点表示,则需要迭代它们并转换它们。 (using loop or list comprehension, ..) (使用循环或列表理解,..)

>>> for f in floats:
...     print(' '.join('0x{:02x}'.format(c) for c in struct.pack('>d', f)))
...
0x40 0x09 0x1e 0xb8 0x51 0xeb 0x85 0x1f
0x40 0x05 0x99 0x99 0x99 0x99 0x99 0x9a
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xbf 0xf0 0x00 0x00 0x00 0x00 0x00 0x00
0x3f 0xf1 0x99 0x99 0x99 0x99 0x99 0x9a

You want to unpack as double but in the program you use the specifier for float : f . 您想要解压缩为double但在程序中使用floatf的说明符。 So that's what you get: 这就是你得到的:

c3 f5 48 40 for 3.14

(See python struct pack double for why you see some ASCII characters.) (有关为什么看到某些ASCII字符,请参阅python struct pack double 。)

This code will print out one line of hex per number: 此代码将为每个数字打印出一行十六进制:

import struct
floats = [3.14, 2.7, 0.0, -1.0, 1.1]
s = []
for f in floats:
    s.append(struct.pack('d', f))
print("The bytes:")
for floatInHex in s:
  for byteval in floatInHex:
    print ('%02x' % byteval, end=""),
  print ()

Result: 结果:

The bytes:
1f85eb51b81e0940
9a99999999990540
0000000000000000
000000000000f0bf
9a9999999999f13f

Python is outputting that "strange" behavior on print because the print function will try to print any ASCII-printable character as ASCII, not hex. Python在打印时输出“奇怪”行为,因为print功能会尝试将任何ASCII可打印字符打印为ASCII, 而不是十六进制。

It prints correctly with binascii because that never prints ASCII characters, only hex characters. 它使用binascii正确打印,因为它从不打印ASCII字符,只打印十六进制字符。

Had me fooled too! 让我上当了! Was about to ask the same question, then found this here: Python Bytearray Printing 即将问同样的问题,然后在这里找到: Python Bytearray Printing

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM