float.hex()

The lossless text form. Decimal output has to round somewhere; hex output shows the stored bits exactly, which makes round trips and bug reports reliable.

Float methodPython 2.6+Live demo
Common call
x.hex()
Returns
str like '0x1.8000000000000p+0' — mantissa, then a binary exponent
Replaces
repr(x) when you need an exact, portable round trip
Watch out
the p exponent is a power of TWO, not of sixteen
float.hex()
→ str

Demo

Live evaluation
Try:
Inputs
nfloata number, e.g. 255.0 or 0.5
Output
float(1).hex()
'0x1.0000000000000p+0'

The output reads as mantissa, then p, then a power of two. 0x1.8p+0 means 1.5 x 2**0, because the hex digits after the point are sixteenths: 8/16 is a half. 255.0 becomes 0x1.fe00000000000p+7, or 1.9921875 x 2**7. Zero is the special case, printing as 0x0.0p+0 with no leading one. Watch the 0.1 case — the long string of digits is exactly why 0.1 is not really a tenth.

Common patterns

Round-trip a float exactly
fromhex reverses hex with no rounding, on any platform.
text = x.hex()
assert float.fromhex(text) == x
Report a float precisely in a bug report
Removes all doubt about which value is actually stored.
log.error("got %s (%s)", value, value.hex())
Compare two floats bit for bit
Equal hex means identical bits; the printed decimals can match while the values differ.
same_bits = a.hex() == b.hex()

Examples

1. One
(1.0).hex()
Returns
'0x1.0000000000000p+0'
2. A half
(0.5).hex()
Returns
'0x1.0000000000000p-1'
3. 255
(255.0).hex()
Returns
'0x1.fe00000000000p+7'
4. Zero
(0.0).hex()
Returns
'0x0.0p+0'
5. Negative
(-0.5).hex()
Returns
'-0x1.0000000000000p-1'
6. Infinity
float('inf').hex()
Returns
'inf'

Pitfalls

1. The p exponent counts powers of two
The digits are hexadecimal but the exponent is binary. p+7 means times 2**7, not 16**7 — misreading it puts you off by a factor of millions.
Read as base 16
(255.0).hex()   # 0x1.fe...p+7
NOT 1.99 * 16**7
Read as base 2
1.9921875 * 2 ** 7
255.0
2. It is not the built-in hex()
hex() takes an integer and rejects floats outright. float.hex is a method on the value, and the two produce completely different text.
Builtin rejects floats
hex(255.0)
TypeError: 'float' object cannot be interpreted as an integer
Call the method
(255.0).hex()
'0x1.fe00000000000p+7'
3. Not meant to be human-readable
It is an exact interchange format, not a display format. Showing it to users trades a familiar number for one almost nobody can read at a glance.
Unreadable output
print(f"Total: {total.hex()}")
Total: 0x1.91eb851eb851fp+6
Format for humans
print(f"Total: {total:.2f}")
Total: 100.48

When to use

Use it
  • Exact round trips through text, with fromhex
  • Bug reports and test fixtures where the precise value matters
  • Comparing floats bit for bit
  • Storing floats in a text format without rounding
Reach for something else
  • Anything a person will read → f-strings or format
  • Integers → the built-in hex()
  • Exact decimal arithmetic → decimal.Decimal

Notes

Complexity
O(1) — formats a fixed number of digits
Return
A new str; always 13 mantissa digits for normal values
CPython impl
Objects/floatobject.c :: float_hex
Memory
Allocates the result string
Thread-safe
Yes — floats are immutable

FAQ

The mantissa is 1 plus 8/16, so 1.5, and p+0 multiplies by 2**0. Hex digits after the point are sixteenths, then two-hundred-fifty-sixths, and so on — the same idea as decimal places, in base 16.

float.fromhex("0x1.8p+0")
# 1.5

History

2.6
float.hex and float.fromhex added together for exact round trips.