Duda con python pack y unpack

0
(0)

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

!!!!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

3 thoughts on “Duda con python pack y unpack

  1. 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
    1. 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.

      1. 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.

Leave a Reply