float.fromhex()

A classmethod, called on the type. The 0x prefix is optional, which is the source of its one genuinely nasty surprise.

Float classmethodPython 2.6+Live demo
Common call
float.fromhex('0x1.8p+0')
Returns
float — exact, with no rounding
Replaces
float(s) when the text is hexadecimal rather than decimal
Watch out
'0.5' parses as HEX and gives 0.3125, not one half
float.fromhex(stringstring — A hexadecimal float such as '0x1.8p+0'. The 0x prefix and the p exponent are both optional. Also accepts 'inf', '-inf' and 'nan'. Leading and trailing whitespace is ignored.type: str · required)
→ float

Demo

Live evaluation
Try:
Inputs
sstrhex float, e.g. 0x1.8p+0
Output
float.fromhex('0x1.8p+0')
1.5

fromhex reads the format float.hex produces: a hex mantissa, then p and a power of two. Look hard at the third case. Because the 0x prefix is optional, the string "0.5" is parsed as HEXADECIMAL — the digit after the point is sixteenths, so it means 5/16, or 0.3125. It does not mean one half, and nothing warns you. Anything that is not a valid hex float raises ValueError.

Parameters

NameTypeRequiredDescription
stringstryesA hexadecimal float such as '0x1.8p+0'. The 0x prefix and the p exponent are both optional. Also accepts 'inf', '-inf' and 'nan'. Leading and trailing whitespace is ignored.

Return value

float — The float the string represents. Raises ValueError if the string is not a valid hexadecimal float.

Common patterns

Round-trip a float exactly
The pairing fromhex is built for — no rounding in either direction.
assert float.fromhex(x.hex()) == x
Read exact constants from a config
Stores a float in text without trusting decimal parsing.
epsilon = float.fromhex(config["epsilon_hex"])
Reproduce a value from a bug report
Recreates the exact bits someone else saw.
value = float.fromhex("0x1.91eb851eb851fp+1")

Examples

1. One and a half
float.fromhex('0x1.8p+0')
Returns
1.5
2. Power of two
float.fromhex('0x1p+8')
Returns
256.0
3. No prefix is hex
float.fromhex('0.5')
Returns
0.3125 # NOT 0.5
4. Round trip
float.fromhex((255.0).hex())
Returns
255.0
5. Infinity
float.fromhex('inf')
Returns
inf
6. Invalid raises
float.fromhex('zz')
Returns
ValueError: invalid hexadecimal floating-point string

Pitfalls

1. '0.5' means 0.3125
The worst trap here by a distance. The 0x prefix is optional, so a decimal-looking string is still read as hexadecimal — 0.5 becomes 5/16. It parses cleanly and returns a plausible number, so nothing flags the mistake.
Silently wrong
float.fromhex('0.5')
0.3125
Use float() for decimal
float('0.5')
0.5
2. It is a classmethod, not a builtin
Call it on the type — float.fromhex(s). There is no bare fromhex() function, and calling it on an instance works but reads as though the instance mattered.
No such builtin
fromhex('0x1p+0')
NameError: name 'fromhex' is not defined
Call on the type
float.fromhex('0x1p+0')
1.0
3. The p exponent is a power of two
Same trap as float.hex in reverse. p+8 multiplies by 2**8, so 0x1p+8 is 256 — not 16**8, and not 108.
Read as base 16
float.fromhex('0x1p+8')   # expected 16**8?
256.0
It is 2**8
1 * 2 ** 8
256
4. It does not accept Python float literals
Decimal exponent notation like 1e5 is not part of the grammar — e is a valid hex DIGIT, so the string is read as digits instead and the meaning changes completely.
Not what you meant
float.fromhex('1e5')
485.0 # 0x1e5, not 100000.0
Use float()
float('1e5')
100000.0

When to use

Use it
  • Reading back a value written with float.hex
  • Exact constants in config files or test fixtures
  • Reproducing a precise float from a bug report
Reach for something else
  • Ordinary decimal text → float(s)
  • User input of any kind → the hex-by-default rule will bite
  • Exact decimal arithmetic → decimal.Decimal

Notes

Complexity
O(len(string)) — a single parse
Return
A new float; exact for any string float.hex produced
CPython impl
Objects/floatobject.c :: float_fromhex
Memory
No allocation beyond the float itself
Thread-safe
Yes — floats and strings are immutable

FAQ

Because the whole string is hexadecimal, prefix or not. The digit after the point is a count of sixteenths, so 5 means 5/16 = 0.3125. If you meant ordinary decimal text, float() is the function you want.

float.fromhex('0.5')   # 0.3125
float('0.5')           # 0.5

History

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