Help need with converting Hex string to IEEE format float

I

i_vincent

Hi all,

Newbie Python programmer here, so please be patient. I have spent all
day googling for an answer to my problem, but everything I try fails to
work (or works from the Interpreter with a set value but not from my
code with dynamic values).

Okay, here is the general gist of the problem. I am using Python to
parse an output file (from a MAK Logger but that is not really
important). Now I have some data that is contained on a line in this
file like:

80 00 00 00

Each of these numbers is a Hex byte making up a four byte (32 bit
Big-Endian) IEEE float. I have read this data into Python using
readlines and then line.split(). This gives me:

['80', '00', '00', '00']

I am then reading these in as:

wib[0] + wib[1] + wib[2] + wib[3] = 8000000 as a string

Now this is the point where I get stuck, I have tried various ways of
implementing the pack/unpack methods of the struct module but with no
luck.

One example I tried was:

wibble = struct.unpack("f", struct.pack("l", long(conv_str, 16)))
OverflowError: long int too large to convert to int

If I follow the examples I have found on the net using a set value of
0x80000000 in them, everything works fine from the interpreter line.

Arrrggggghhhh.

Everything has worked really easily up this point but I am now stuck
completely, I would be grateful for any help people can offer.
Regards

Ian Vincent
 
F

Fredrik Lundh

Newbie Python programmer here, so please be patient. I have spent all
day googling for an answer to my problem, but everything I try fails to
work (or works from the Interpreter with a set value but not from my
code with dynamic values).

Okay, here is the general gist of the problem. I am using Python to
parse an output file (from a MAK Logger but that is not really
important). Now I have some data that is contained on a line in this
file like:

80 00 00 00

Each of these numbers is a Hex byte making up a four byte (32 bit
Big-Endian) IEEE float. I have read this data into Python using
readlines and then line.split(). This gives me:

['80', '00', '00', '00']

how about:

# convert to byte string
import struct
s = "".join([chr(int(c, 16)) for c in x])
v = struct.unpack("!f", s)

or

# convert to byte string, via the array module
import array, struct
a = array.array("B", [int(c, 16) for c in x])
v = struct.unpack("!f", )

</F>
 
F

Fredrik Lundh

# convert to byte string, via the array module
import array, struct
a = array.array("B", [int(c, 16) for c in x])
v = struct.unpack("!f", )

eh? should be:

# convert to byte string, via the array module
import array, struct
a = array.array("B", [int(c, 16) for c in x])
v = struct.unpack("!f", a)

</F>
 
M

Max M

Each of these numbers is a Hex byte making up a four byte (32 bit
Big-Endian) IEEE float. I have read this data into Python using
readlines and then line.split(). This gives me:

['80', '00', '00', '00']


Oh, programmers loves this kind stuff. You should get tons of answers.

##
st = '80 00 00 00'

import binascii
import struct

s = ''.join([binascii.a2b_hex(s) for s in st.split()])
v = struct.unpack("f", s)[0]
print v
##

regards Max M

--

hilsen/regards Max M, Denmark

http://www.mxm.dk/
IT's Mad Science
 
F

Fredrik Lundh

Max said:
Oh, programmers loves this kind stuff. You should get tons of answers.

data = '80 00 00 00'

import Image
v = Image.fromstring("F", (1, 1), data, "hex", "F;32BF").getpixel((0, 0))

</F>
 
C

Christos TZOTZIOY Georgiou

how about:

# convert to byte string
import struct
s = "".join([chr(int(c, 16)) for c in x])
v = struct.unpack("!f", s)

I think that the third line in the snippet above could also be:

s = "".join(x).decode("hex")

I am not sure I remember in which version of Python the hex codec was
added, but it is handy.
 
P

Peter Hansen

Christos said:
s = "".join(x).decode("hex")

I am not sure I remember in which version of Python the hex codec was
added, but it is handy.

Of course, binascii could do this since 2.0 or so, but not
having to import another module *is* nice:
'\xff\x12'
'\xff\x12'

Thanks for pointing it out, Christos.
 
R

Richard Brodie

One example I tried was:

wibble = struct.unpack("f", struct.pack("l", long(conv_str, 16)))
OverflowError: long int too large to convert to int

You can't fit 0x80000000L into a signed 32-bit integer, use 'L' for
an unsigned one.
If I follow the examples I have found on the net using a set value of
0x80000000 in them, everything works fine from the interpreter line.

This depends on the Python version: before 2.4 0x80000000
corresponds to the bit pattern you expect but will be negative.
That's why it's happy as a signed 32-bit integer.
<interactive input>:1: FutureWarning: hex/oct constants > sys.maxint
will return positive values in Python 2.4 and up
....
False
 
I

Ian Vincent

Max M said:
##
st = '80 00 00 00'

import binascii
import struct

s = ''.join([binascii.a2b_hex(s) for s in st.split()])
v = struct.unpack("f", s)[0]
print v
##

This one worked great for what I was trying to do.

Thanks to everybody for your help.

TTFN

Ian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top