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

Tim Peters tim.peters at
Sun Jan 16 12:28:00 EST 2005

[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\x80\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\x80\x7f')[0]
> 1.#QNAN


Those specific accidents are reliable on the box you're using.

> BTW, your example:
> >>> struct.unpack('f','\xcd\xcc\x8c\x3f')[0]
> 1.1000000238418579
> >>> i32f(0x3f8ccccd)
> 1.1000000238418579
> 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\x80\x7f')[0]
> 1.#INF

Entirely determined by the platform C compiler and hardware.

> >>> struct.unpack('<f','\x00\x00\x80\x7f')[0]
> 3.4028236692093846e+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.

More information about the Python-list mailing list