2016-05-14 3 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.

EDIT

Видимо я должен использовать 'd' вместо 'f', поскольку я использую двойной точности с плавающей запятой на моей машине. Благодарю вас. Rad Lexus для вашего ответа. Но я все еще немного озадачен выводами 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 байт. Этого я и ожидал. Но некоторые записи короче. Во всяком случае, нет записи, которая дает правильное 8-байтовое представление соответствующего числа с плавающей точкой - за исключением float 0.0.

Ваш код продолжает с некоторой магии, чтобы извлечь фактические правильные 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. Пожалуйста, проверьте ** EDIT ** по моему вопросу. Огромное спасибо. –

+1

@ K.Mulier, Python repesent character i строка как символ (вместо экранированного шестнадцатеричного формата), если он представлен таким образом. 'b '@' == b '\ x40'' – falsetru

+0

Большое вам спасибо. В этом случае вещи начинают меня понимать. Тем не менее, я заметил, что последовательность байтов изменяется по порядку. Это верно? –

1

Вы хотите распаковать в double, но в программе используется спецификатор для float: f. Так вот что вы получите:

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. Пожалуйста, проверьте ** EDIT ** по моему вопросу. Огромное спасибо. @Rad Lexus –

Смежные вопросы