2016-05-14 120 views
1

Python有时会产生奇怪的隐含字节数组。我不知道如何解释它们。Python输出奇怪的bytearray

考虑下面的例子。

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) 

struct.pack函数应该输出列表中每个值的'字节表示'。该列表由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 

顺便说一句,我用下面的网站做出正确的转换:http://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html

不幸的是,Python不会输出我期望的那些字节。相反,Python输出一些非常神秘的字节列表。但是这真的是一个字节列表? Python输出的东西太奇怪了:

b'\xc3\[email protected]\xcd\xcc,@\x00\x00\x00\x00\x00\x00\x80\xbf\xcd\xcc\x8c?' 

请帮我理解Python在这里做什么。

编辑

显然我应该用'd'代替'f',因为我使用的是双精度浮点数我的机器上。谢谢你先生。雷克萨斯为您的答案。但是我仍然对Python的输出感到困惑。让我澄清一下。

我开始,你给了我下面的代码:

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

在开始之前,我检查对象s得到什么正在发生的把握。这是我从s得到:

>>> s 
[ b'\x1f\x85\xebQ\xb8\x1e\[email protected]', 
    b'\x9a\x99\x99\x99\x99\x99\[email protected]', 
    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?'  ] 

s一些条目是8个字节长。这是我所期望的。但有些条目较短。无论如何,除了浮点数0.0之外,没有条目给出相应浮点数的正确8字节表示。

您的代码具有一些特殊继续每浮动提取实际正确的8个字节:

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

现在我们得到正确的结果。但为什么s对象还没有包含每个浮点8位的正确值?为什么需要这种额外的魔法?

回答

2

>>> 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' 

如果你想单独获得每个浮点表示,需要迭代他们和他们CONVER。 (使用循环或列表理解,..)

>>> 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 
+0

我对Python输出的内容仍然有点困惑。请在我的问题上检查**编辑**。非常感谢。 –

+1

@ K.Mulier,Python重复字符我是一个字符串作为一个字符(而不是转义的十六进制格式),如果它可以用这种方式表示的话。 'b'@'== b'\ x40'' – falsetru

+0

非常感谢。在那种情况下,事情开始对我有意义。但我注意到,字节顺序是按顺序颠倒的。那是对的吗? –

1

你想解开的double,但在程序中使用的说明符floatf。所以这就是你会得到什么:

c3 f5 48 40 for 3.14 

(见python struct pack double为什么你看到一些ASCII字符)。

这段代码会打印出每个号码十六进制的一行:

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() 

结果:

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

我对Python输出的内容仍然有些困惑。请在我的问题上检查**编辑**。非常感谢。 @Rad Lexus –