float#

float is a 64-bit IEEE 754 double. Same rounding pitfalls as every other language with IEEE doubles. The operator’s instinct should be to reach for decimal.Decimal whenever money, totals, or exact comparisons matter.

0.1 + 0.2                       # 0.30000000000000004
1.0 == 0.1 + 0.2 + 0.7          # False

from decimal import Decimal
Decimal("0.1") + Decimal("0.2")  # Decimal("0.3")

Special values are first-class.

import math

math.inf, -math.inf, math.nan
math.isnan(x); math.isfinite(x)

Division by zero on floats produces ZeroDivisionError, not inf. To get IEEE behaviour use numpy or compute explicitly.

Methods#

Method

Effect

is_integer()

True when the value has no fractional part.

as_integer_ratio()

Pair of ints (numerator, denominator) exactly representing the value.

hex()

Hexadecimal string representation ("0x1.8p+1").

float.fromhex(s)

Parse a hexadecimal string back to float (classmethod).

conjugate()

Complex conjugate (returns the same float).

is_integer is the operator’s check for “did this divide cleanly”.

(3.0).is_integer(), (3.14).is_integer()
(True, False)

as_integer_ratio recovers the exact rational the float represents.

(0.5).as_integer_ratio()
(1, 2)

hex and float.fromhex round-trip a float without going through decimal text.

(1.5).hex()
'0x1.8000000000000p+0'
float.fromhex('0x1.8000000000000p+0')
1.5

Operator overloading#

float implements the standard numeric dunder methods.

Operator

Dunder

Returns

a + b

__add__

Sum.

a - b

__sub__

Difference.

a * b

__mul__

Product.

a / b

__truediv__

True division.

a // b

__floordiv__

Floor division.

a % b

__mod__

Modulo (IEEE remainder).

a ** b

__pow__

Exponentiation.

-a

__neg__

Negation.

abs(a)

__abs__

Absolute value.

round(a, n)

__round__

Banker’s rounding.

a == b

__eq__

Equality (with IEEE NaN caveats).

a < b

__lt__

Less than.

hash(a)

__hash__

Hash (consistent with int when integral).

int(a)

__int__

Truncating integer conversion.

float(a)

__float__

Float conversion.

bool(a)

__bool__

False only for 0.0.

__r*__ reflected forms and __i*__ in-place forms exist for every binary operator above.

A vector class with __add__ and __mul__ lets the operator do float arithmetic on a pair.

class Vec2:
    def __init__(self, x, y): self.x, self.y = x, y
    def __add__(self, other): return Vec2(self.x + other.x, self.y + other.y)
    def __mul__(self, k):     return Vec2(self.x * k, self.y * k)
    def __repr__(self):       return f"Vec2({self.x}, {self.y})"

Vec2(1.0, 2.0) + Vec2(3.5, 4.0)
Vec2(4.5, 6.0)

Reflected __rmul__ makes 2.0 * v work even when the float is on the left (it returns NotImplemented first; Python then asks v).

class Vec2:
    def __init__(self, x, y): self.x, self.y = x, y
    def __mul__(self, k):  return Vec2(self.x * k, self.y * k)
    def __rmul__(self, k): return self.__mul__(k)
    def __repr__(self):    return f"Vec2({self.x}, {self.y})"

3.0 * Vec2(1.0, 2.0)
Vec2(3.0, 6.0)

References#