Duda con python pack y unpack

hola, estoy tratando de construir una aplicación que requiere enviar
flotantes a través de la capa de red
por eso necesito obtener la representación hexadecimal para enviar
byte por byte.

Pero al usar pack
>>> struct.pack(“>f”,0.8)
‘?L\xcc\xcd’
deberían ser 4 bytes no?

Algo como esto :
>>> struct.unpack(“>f”, “\x3f\x4c\xcc\xcd”)
(0.80000001192092896,)

Sin embargo python parece saber como interpretar el resultado previo:

>>> struct.unpack(“>f”, “?L\xcc\xcd”)
(0.80000001192092896,)

!!!!


0 votes, average: 0.00 out of 50 votes, average: 0.00 out of 50 votes, average: 0.00 out of 50 votes, average: 0.00 out of 50 votes, average: 0.00 out of 5 (0 votes, average: 0.00 out of 5)
You need to be a registered member to rate this post.
Loading...
Pregúntale al gurú, Programacion, Python | RSS 2.0 |     438 views

RSS feed

3 Comments »

Comment by gwolf
2009-02-23 12:50:26

Lo que ves es completamente normal – y no privativo de Python:

$ perl -e 'print unpack("f", pack("f", 0.8))'
0.8000000119209290

¿Por qué? Porque estás hablando de punto flotante. La aritmética de punto flotante te da gran flexibilidad en el rango en el cual puedes operar (porque no guarda la cantidad tal cual, sino que la cantidad y su magnitud), pero pierde precisión en los dígitos menos significativos. Vamos, igual que con 0.8, esto podrías haberlo visto con números muy grandes:

$ perl -e 'for my $exp (-10..20) {print "8 * 10 ^ $exp: ", unpack("f", pack("f", 8*10**$exp)),"n"}'
8 * 10 ^ -10: 8.00000010681146e-10
8 * 10 ^ -9: 7.99999977374455e-09
8 * 10 ^ -8: 7.99999995138023e-08
8 * 10 ^ -7: 8.00000009348878e-07
8 * 10 ^ -6: 7.99999997980194e-06
8 * 10 ^ -5: 7.999999797903e-05
8 * 10 ^ -4: 0.0007999999797903
8 * 10 ^ -3: 0.00800000037997961
8 * 10 ^ -2: 0.0799999982118607
8 * 10 ^ -1: 0.800000011920929
8 * 10 ^ 0: 8
8 * 10 ^ 1: 80
8 * 10 ^ 2: 800
8 * 10 ^ 3: 8000
8 * 10 ^ 4: 80000
8 * 10 ^ 5: 800000
8 * 10 ^ 6: 8000000
8 * 10 ^ 7: 80000000
8 * 10 ^ 8: 800000000
8 * 10 ^ 9: 8000000000
8 * 10 ^ 10: 80000000000
8 * 10 ^ 11: 799999983616
8 * 10 ^ 12: 7999999967232
8 * 10 ^ 13: 79999998623744
8 * 10 ^ 14: 800000003014656
8 * 10 ^ 15: 7.99999989592883e+15
8 * 10 ^ 16: 8.00000021805138e+16
8 * 10 ^ 17: 7.999999874454e+17
8 * 10 ^ 18: 7.999999874454e+18
8 * 10 ^ 19: 7.99999998440516e+19
8 * 10 ^ 20: 8.00000016032702e+20
Comment by huguin
2009-02-23 13:58:19

gracias gunnar!
a lo que me refería es que no entendía la respuesta de python a la instrucció unpack, que da esto
‘?L\xcc\xcd’,
hasta que me di cuenta que cuando le pides al shell que te muestre el contenido,
trata de imprimir ASCII’s (¿es correcto este plural?), cuando puede y si no puede usa ya las secuencias de
escape \x. Realmente en la memoria si hay un 3f 4c cc cd , solo que el 3f lo imprime porque es ASCII como ? y el 4c como L. Pero yo quería ver que python me dijiese \x3f\x4c\xcc\xcd, pero bueno eso me saco por newbie.

Comment by gwolf
2009-02-24 08:30:21

Hoy en día, ya no puedes asumir que cualquier representación interna de objetos opacos sea representable como caracteres. No, no estás hablando ya de caracteres ASCII (ese es el plural correcto – ASCII se refiere a _un_ estándar, y no puede por tanto ser pluralizado; “caracter ASCII” es el singular, “caracteres ASCII” el plural) – ASCII va de 0x00 a 0x7F (o del 0 al 128), de los cuales los primeros 32 caracteres no necesariamente tienen representación imprimible. En el caso de tu ejemplo tienes un 0xCC y un 0xCD, que caben en algunas extensiones a ASCII (como ISO-8859-1)… Pero si tu consola es Unicode, tienes cadenas inválidas.
Pack y unpack sirven para manejar representaciones binarias – no los uses con un print. En todo caso, rodéalos de algún serializador, como YAML.

 
 
 
Name (required)
E-mail (required - never shown publicly)
URI
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> in your comment.

Trackback responses to this post