473,856 Members | 1,713 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

interpret 4 byte as 32-bit float (IEEE-754)

Hello,

I've read some bytes from a file and just now I can't interpret 4 bytes
in this dates like a real value.

An extract from my program

def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)

....

value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

Anybody an answer ?

regards
gf
Jul 18 '05 #1
9 9825
franzkowiak wrote:
I've read some bytes from a file and just now I can't interpret 4 bytes
in this dates like a real value. An extract from my program:
def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
...
value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)

I was suspicious of that first byte, thought it might be an exponent,
since it seemed to have too many on bits in a row to be part of 1.11.

-Scott David Daniels
Sc***********@A cm.Org
Jul 18 '05 #2
On 2005-01-15, Scott David Daniels <Sc***********@ Acm.Org> wrote:
I've read some bytes from a file and just now I can't interpret 4 bytes
in this dates like a real value.
OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)


Just be careful. That doesn't work for all 32-bit IEEE floating
point values:
import struct
bytes = '\xff\xff\xff\x ff'
print struct.unpack(' >f',bytes)

(-6.8056469327705 772e+38,)

0xffffff is _not_ -6.8...e38. It's a NaN.

IIRC, it doesn't work for infinities either. I haven't tried
denormals.

--
Grant Edwards grante Yow! It's hard being
at an ARTIST!!
visi.com
Jul 18 '05 #3
Scott David Daniels schrieb:
franzkowiak wrote:
I've read some bytes from a file and just now I can't interpret 4
bytes in this dates like a real value. An extract from my program:
def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) +
(ord(c[3])<<24)
...
value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)

I was suspicious of that first byte, thought it might be an exponent,
since it seemed to have too many on bits in a row to be part of 1.11.

-Scott David Daniels
Sc***********@A cm.Org


Ok, I the string exist with "mystr = f.read(4)" and the solution for
this case is in your line "struct.unpack( '>f', bytes)"
But what can I do when I want the interpret the content from the Integer
myInt (*myInt = 0x3F8CCCCD) like 4-byte-real ?
This was stored with an othes system in a binary file to
CD CC 8C 3F and now is it in python in value. The conversion is not
possible. It's right... one of this bytes is an exponent.
I want copy the memory content from the "value address" to "myReal
address" and use print "%f" %myReal.
Is myReal then the right format ?
What can I do with python, in FORTH is it simple
( >f f. )

gf

Jul 18 '05 #4
G.Franzkowiak wrote:
Scott David Daniels schrieb:
franzkowiak wrote:
I've read some bytes from a file and just now I can't interpret 4
bytes in this dates like a real value. An extract from my program:
def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) +
(ord(c[3])<<24)
...
value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)

I was suspicious of that first byte, thought it might be an exponent,
since it seemed to have too many on bits in a row to be part of 1.11.

-Scott David Daniels
Sc***********@A cm.Org

Ok, I the string exist with "mystr = f.read(4)" and the solution for
this case is in your line "struct.unpack( '>f', bytes)"
But what can I do when I want the interpret the content from the Integer
myInt (*myInt = 0x3F8CCCCD) like 4-byte-real ?
This was stored with an othes system in a binary file to
CD CC 8C 3F and now is it in python in value. The conversion is not
possible. It's right... one of this bytes is an exponent.
I want copy the memory content from the "value address" to "myReal
address" and use print "%f" %myReal.
Is myReal then the right format ?
What can I do with python, in FORTH is it simple
( >f f. )

gf

If you really want to do this kind of byte fiddling:
http://members.dsl-only.net/~daniels/block.html

Then:
from block import Block, View
b = Block(4) # enough space for one float (more is fine)
iv = View('i', b) # getting to it as an integer
fv = View('f', b) # same memory as floating point
iv[0] = 0x3F8CCCCD # Here is a sample just using the integer
print fv[0]

On an Intel/Amd/Generic "PC" machine, you should get 1.1

-Scott David Daniels
Sc***********@A cm.Org
Jul 18 '05 #5

"Scott David Daniels" <Sc***********@ Acm.Org> wrote in message
news:41******** @nntp0.pdx.net. ..
franzkowiak wrote:
I've read some bytes from a file and just now I can't interpret 4 bytes
in this dates like a real value. An extract from my program:
def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) +
(ord(c[3])<<24)
...
value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)

I was suspicious of that first byte, thought it might be an exponent,
since it seemed to have too many on bits in a row to be part of 1.11.


I believe exponents are typically stored as a positive offset from the
largest negative exponent. 3F8 is about half of 7FF, so that seems about
right for an actual exponent of 0.

Terry J. Reedy

Jul 18 '05 #6
Scott David Daniels schrieb:
G.Franzkowiak wrote:
Scott David Daniels schrieb:
franzkowiak wrote:

I've read some bytes from a file and just now I can't interpret 4
bytes in this dates like a real value. An extract from my program:
def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) +
(ord(c[3])<<24)
...
value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)

I was suspicious of that first byte, thought it might be an exponent,
since it seemed to have too many on bits in a row to be part of 1.11.

-Scott David Daniels
Sc***********@A cm.Org


Ok, I the string exist with "mystr = f.read(4)" and the solution for
this case is in your line "struct.unpack( '>f', bytes)"
But what can I do when I want the interpret the content from the
Integer myInt (*myInt = 0x3F8CCCCD) like 4-byte-real ?
This was stored with an othes system in a binary file to
CD CC 8C 3F and now is it in python in value. The conversion is not
possible. It's right... one of this bytes is an exponent.
I want copy the memory content from the "value address" to "myReal
address" and use print "%f" %myReal.
Is myReal then the right format ?
What can I do with python, in FORTH is it simple
( >f f. )

gf

If you really want to do this kind of byte fiddling:
http://members.dsl-only.net/~daniels/block.html

Then:
from block import Block, View
b = Block(4) # enough space for one float (more is fine)
iv = View('i', b) # getting to it as an integer
fv = View('f', b) # same memory as floating point
iv[0] = 0x3F8CCCCD # Here is a sample just using the integer
print fv[0]

On an Intel/Amd/Generic "PC" machine, you should get 1.1

-Scott David Daniels
Sc***********@A cm.Org


That's good :-))
I'm missing the makefile ;-)
I'm using the other world... right

Thank you

Jul 18 '05 #7
G.Franzkowiak wrote:
Scott David Daniels schrieb:
If you really want to do this kind of byte fiddling:
http://members.dsl-only.net/~daniels/block.html
Then:
from block import Block, View
b = Block(4) # enough space for one float (more is fine)
iv = View('i', b) # getting to it as an integer
fv = View('f', b) # same memory as floating point
iv[0] = 0x3F8CCCCD # Here is a sample just using the integer
print fv[0]
On an Intel/Amd/Generic "PC" machine, you should get 1.1


That's good :-))
I'm missing the makefile ;-)
I'm using the other world... right

There's a lot more than one other world. distlib is your friend.

There is no makefile. If you are not on a windows box,
get the source, extract the files from the zip, and run:

python setup.py install

-Scott David Daniels
Sc***********@A cm.Org
Jul 18 '05 #8
On Sat, 15 Jan 2005 11:00:36 -0800, Scott David Daniels <Sc***********@ Acm.Org> wrote:
G.Franzkowia k wrote:
Scott David Daniels schrieb:
franzkowiak wrote:

I've read some bytes from a file and just now I can't interpret 4
bytes in this dates like a real value. An extract from my program:
def l32(c):
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) +
(ord(c[3])<<24)
...
value = l32(f.read(4)) <--- 3F 8C CC CD should be 1.11

OK, here's the skinny (I used blocks & views to get the answer):

import struct
bytes = ''.join(chr(int (txt, 16)) for txt in '3F 8C CC CD'.split())
struct.unpack(' >f', bytes)

I was suspicious of that first byte, thought it might be an exponent,
since it seemed to have too many on bits in a row to be part of 1.11.

-Scott David Daniels
Sc***********@A cm.Org

Ok, I the string exist with "mystr = f.read(4)" and the solution for
this case is in your line "struct.unpack( '>f', bytes)"
But what can I do when I want the interpret the content from the Integer
myInt (*myInt = 0x3F8CCCCD) like 4-byte-real ?
This was stored with an othes system in a binary file to
CD CC 8C 3F and now is it in python in value. The conversion is not
possible. It's right... one of this bytes is an exponent.
I want copy the memory content from the "value address" to "myReal
address" and use print "%f" %myReal.
Is myReal then the right format ?
What can I do with python, in FORTH is it simple
( >f f. )

gf

If you really want to do this kind of byte fiddling:
http://members.dsl-only.net/~daniels/block.html

Then:
from block import Block, View
b = Block(4) # enough space for one float (more is fine)
iv = View('i', b) # getting to it as an integer
fv = View('f', b) # same memory as floating point
iv[0] = 0x3F8CCCCD # Here is a sample just using the integer
print fv[0]

On an Intel/Amd/Generic "PC" machine, you should get 1.1

Ok, for most bit patterns (except QNANs), you can do it in pure python:

----< i32as_single.py >------------------------------------
class NoQNAN(ValueErr or): pass # use to flag inability to return QNANs

def i32as_single(i) :
"""
(UIAM in my interpretation of a 1995 Pentium Processor Developer's Manual)
This converts bits in a 32-bit integer as if they were bits
of a single-precision IEEE 754 floating point number to python float

+---+---+---+---+---+---+---+---+---+---+---+---+ ... +---+---+---+---+
| s | e e e e e e e eb| b b b ... b b b b0 |
+---+---+---+---^---+---+---+---^---+---+---+---^ ... ^---+---+---+---+
31 30 29 28 27 26 25 24 23 22 21 20 3 2 1 0

where s is the sign bit, and is the only thing that changes between + and -
and e..eb is an 8-bit biased (by 127) exponent, and eb is the hidden
unit 1 bit followed by 23 b..b0 significant "fraction" bits",
normalized so that the most significant bit is always 1 and therefore
doesn't have to be stored at eb, except that when all but the sign bit
are zero, eb is ignored and the value is then a signed zero value.
The binary fraction starting bit is after the hidden '1' bit eb at 23,
so viewing bits 0..23 as an integer, we have to divide by 2**23 (or
adjust the exponent) to get the 1.xxxx values when the official unbiased
exponent is zero (offset value 127). Thus 0x3f800000 is zero unbiased
exponent and no other bits, for a value of 1.0

A biased exponent of 255 signifies a NaN, and a biased exponent of
zero signifies a denormal (which doesn't have a hidden bit, and whose
unit bit is bit 22). Single precision denormals can be normalized
in python (double) float format, which is done for the return value.
"""
signbit = i&0x80000000
if not i&0x7fffffff: return signbit and -0.0 or 0.0 # if -0.0 available
biased_exp = (i>>23) & 0xff # bits 30-23
unitbit = biased_exp and 0x800000 or 0 # bit 23, or 0 for denormals
significand = i & 0x7fffff # bits 22-0
if biased_exp == 255:
if significand:
raise NoQNAN, "Sorry, can't generate QNAN from %08x" % i
return signbit and -1e9999 or 1e9999 # XXX s/b INF's for sure??
adjexp = (biased_exp or 1) - 127 - 23 # adjusted for denormal
posvalue = (significand + unitbit)*2.0**a djexp
return signbit and -posvalue or posvalue

def test():
import struct
num = 0
for sign in (0, 2*(-2**30)):
for i3 in xrange(128):
num3 = i3<<24
for i2 in xrange(256):
print '\r%08x'%(num,) , # show progress
num2 = i2<<16
# skip mid byte of significand, make 0
# and twiddle only a few bits at the bottom
for num0 in xrange(8):
num = sign+num3+num2+ num0
s = ''.join(map(chr ,(num0, 0, i2,((sign and 0x80 or 0)+i3))))
try: ti32as = i32as_single(nu m)
except NoQNAN: continue
tstruct = struct.unpack(' f', s)[0] # XXX '<f' => no INF ??
if ti32as != tstruct:
print '\n%x =>%r\n%r => %r' % (num, ti32as, s, tstruct)

if __name__ == '__main__':
test()
-----------------------------------------------------------
[21:47] C:\pywk\clp>i32 as_single.py
C:\pywk\clp\i32 as_single.py:31 : FutureWarning: hex/oct constants > sys.maxint will return positi
ve values in Python 2.4 and up
signbit = i&0x80000000
7fff0007C:\pywk \clp\i32as_sing le.py:51: FutureWarning: %u/%o/%x/%X of negative int will return a
signed string in Python 2.4 and up
print '\r%08x'%(num,) , # show progress
ff7f0007C:\pywk \clp\i32as_sing le.py:38: FutureWarning: %u/%o/%x/%X of negative int will return a
signed string in Python 2.4 and up
raise NoQNAN, "Sorry, can't generate QNAN from %08x" % i
fffe0007

Of course, the test() gives a clue how you might write the whole thing using struct
by just summing the four chr-ed extracted bytes from the input i ;-)

Anyway, a couple things (how to make a QNAN in python without calling struct, and '<' in struct):
from i32as_single import i32as_single as i32f
i32f(0x3f8ccccd ) 1.1000000238418 579 i32f(0x00000000 ) 0.0 i32f(0x7f800000 ) 1.#INF i32f(0xff800000 ) -1.#INF

But I don't know how to build QNaNs:
i32f(0x7f800001 ) Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "i32as_single.p y", line 38, in i32as_single
raise NoQNAN, "Sorry, can't generate QNAN from %08x" % i
i32as_single.No QNAN: Sorry, can't generate QNAN from 7f800001

Whereas struct does:
import struct
struct.unpack(' f','\x00\x00\x8 0\x7f')[0] 1.#INF struct.unpack(' f','\x01\x00\x8 0\x7f')[0] 1.#QNAN

BTW, your example: struct.unpack(' f','\xcd\xcc\x8 c\x3f')[0] 1.1000000238418 579 i32f(0x3f8ccccd ) 1.1000000238418 579

But what does this mean? (I wanted to test with little endian unpacking, since
that is what I knew I created, but that isn't what '<' means?? ...)
struct.unpack(' f','\x00\x00\x8 0\x7f')[0] 1.#INF struct.unpack(' <f','\x00\x00\x 80\x7f')[0]

3.4028236692093 846e+038

Regards,
Bengt Richter
Jul 18 '05 #9
[Bengt Richter]
....
But I don't know how to build QNaNs:
You can subtract infinity from infinity. While all Python behavior in
the presence of NaNs, infinities, and signed zeroes is a
platform-dependent accident, it you're on a box that has such things,
and figure out some (accidental!) way to spell infinity, then inf-inf
should return a NaN (although on a WinTel box, it's most likely to be
spelled "-1.#IND" when converted to string).

....
Whereas struct does:
No, it doesn't. All Python behavior in the presence of NaNs,
infinities, and signed zeroes is a platform-dependent accident.
import struct
struct.unpack(' f','\x00\x00\x8 0\x7f')[0] 1.#INF


An accident (both that you got back an infinity, and the string
representation of an infinity).
struct.unpack(' f','\x01\x00\x8 0\x7f')[0] 1.#QNAN


Ditto.

Those specific accidents are reliable on the box you're using.
BTW, your example: struct.unpack(' f','\xcd\xcc\x8 c\x3f')[0] 1.1000000238418 579 i32f(0x3f8ccccd ) 1.1000000238418 579

But what does this mean?
Mostly just that behavior is predictable when you're *not* using
infinities, NaNs or signed zeroes from Python.
(I wanted to test with little endian unpacking, since
that is what I knew I created, but that isn't what '<' means?? ...)


Little-endian is part of what '<' means. '<' also means "use standard
alignment" and "use standard data size" and "use standard bit
representation" . As soon as you force anything like that, Python has
to try to interpret the bits itself. In the absence of "<", ">" and
"!", plain "f" asks for a wholly platform-native result. In that
case, Python doesn't have to know anything about what the bits might
mean: it stores the bytes into a native sizeof(float)-byte memory
area natively aligned for a float, and you get back whatever the
native C thinks that means.
struct.unpack(' f','\x00\x00\x8 0\x7f')[0] 1.#INF


Entirely determined by the platform C compiler and hardware.
struct.unpack(' <f','\x00\x00\x 80\x7f')[0]

3.4028236692093 846e+038


Entirely determined by what Python thinks the bits should mean, but
Python doesn't know anything about infinities, NaNs, or signed zeroes,
and C89 library routines Python calls to construct the value (like
ldexp()) have no portably defined behavior in their presence either.
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
26175
by: Mike | last post by:
I am trying to calculate a 32bit float value from 4 int values. I sucessfully calcluated a 32bit long value: LONG l32BitData = pData; l32BitData <<= 8; l32BitData |= (byte)pData; l32BitData <<= 8; l32BitData |= (byte)pData;
53
8256
by: Zhiqiang Ye | last post by:
Hi, All I am reading FAQ of this group. I have a question about this: http://www.eskimo.com/~scs/C-faq/q7.31.html It says: " p = malloc(m * n); memset(p, 0, m * n); The zero fill is all-bits-zero, and does not therefore guarantee useful null pointer values (see section 5 of this list) or floating-point zero values.
8
18897
by: Kenny ODell | last post by:
I do not know how to convert from a byte array to a float, and back again. I read data from a serial port into a byte (entire command structure which I parse). I am able to sift the data and isolate the information I want, in this case a structure that contains a bunch of floats and longs. So, lets say I have a byte containing the 4 bytes of info that are actually a float. In old C code, I would simple declare a pointer to the correct...
3
5988
by: Aykut | last post by:
Hi I have to convert byte value to float in C#.Float is in IEEE 754 format. byte value is= 70 23 22 195 in a byte array. and its float value is = -150.0909 what is the algoritm for this conversion? thanks for help
0
2939
by: GDB500 | last post by:
Can you help with code to convert from 64bit to 32bit other than just A=B :confused: The full story is that I have a 64bit float in hexidecimal so first I need to get this into a 64bit float Then using ANDs and Divides extract the Exponent and Mantissa and then get it into a 32bit float Thanks
1
2493
by: Jamie Risk | last post by:
I have a four (4) byte array that follows the IEEE 754 format. (It arrives on the windows platform from an embedded system via USB). How can I extract/convert/assign the encoded array to a native float variable? - Jamie
7
4020
by: dzar | last post by:
I have an application that sends messages to other applications through PostMessage(HWND_BROADCAST, MY_MESSAGE_ID, wparam_float, lparam_float); in C (and this works... I can typecast and built byte arrays with whatever I want in C and extract them at the other end just fine). I am now needing to interface with C# and find I cannot do this in an easy way (at least for me). When I try something like: Single sValue= (Single) m.LParam;
29
11132
by: candy_init | last post by:
Hi all, I just came across the following program: #include <stdio.h> int main() { float a = 12.5; printf("%d\n", a); printf("%d\n", *(int *)&a); return 0;
7
7270
by: Mario M. Mueller | last post by:
Hi, I have a binary file containing 3 byte float values (big endian). How can I read them into python? The struct module does not work, since it expects 4 byte floats. Any hints? Mario
0
11056
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10782
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9531
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7932
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5761
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5958
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4575
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4174
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3201
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.