fractions: Fraction ** Fraction Always Returns float (tested)

The whole point of fractions.Fraction is exact arithmetic with no floating-point rounding. We measured what ** does when both the base and the exponent are Fraction objects -- including cases where the mathematically exact answer is itself a whole number or simple fraction.

1. An int exponent keeps the result an exact Fraction

from fractions import Fraction

result = Fraction(9, 1) ** 2
print(result, type(result))
81 <class 'fractions.Fraction'>

Measured: Fraction ** int returns a Fraction, staying exact -- this is the behavior most code implicitly relies on when chaining more Fraction arithmetic afterward.

2. A Fraction exponent returns float -- even for an exact, whole-number answer

from fractions import Fraction

cases = [
    (Fraction(9, 1), Fraction(1, 2)),   # sqrt(9) = 3, exact
    (Fraction(1, 4), Fraction(1, 2)),   # sqrt(1/4) = 1/2, exact
    (Fraction(1, 1), Fraction(1, 2)),   # sqrt(1) = 1, exact
]
for base, exp in cases:
    result = base ** exp
    print(f"{base} ** {exp} = {result}  ({type(result).__name__})")
9 ** 1/2 = 3.0  (float)
1/4 ** 1/2 = 0.5  (float)
1 ** 1/2 = 1.0  (float)

Measured: every one of these has a mathematically exact, perfectly rational answer (3, 1/2, 1) -- yet ** with a Fraction exponent returns a float every time, not a Fraction. The Fraction type doesn't special-case exponents that happen to produce an exact rational result; any non-integer exponent unconditionally falls back to float power.

3. The risk: exactness silently ends at that line, and propagates into everything after it

from fractions import Fraction

exact_chain = Fraction(9, 1) ** 2 + Fraction(1, 3)
print(exact_chain, type(exact_chain))

broken_chain = Fraction(9, 1) ** Fraction(1, 2) + Fraction(1, 3)
print(broken_chain, type(broken_chain))
244/3 <class 'fractions.Fraction'>
3.3333333333333335 <class 'float'>

Measured: once a Fraction ** Fraction expression runs, the result is a plain float, and every Fraction added to it afterward is coerced to float too -- the exact arithmetic Fraction exists for is gone from that point on, with no error or warning. If a calculation needs to raise a Fraction to a root or rational power and stay exact, check whether the specific case is a perfect power first (e.g. via math.isqrt for square roots) rather than relying on ** to preserve exactness.

Frequently asked questions

Does Fraction ** Fraction return an exact Fraction in Python?

No -- we measured it always returning a float, even in cases like Fraction(9,1) ** Fraction(1,2) where the true answer (3) is a whole number and perfectly representable as a Fraction.

Why did my Fraction arithmetic turn into float after a ** operation?

Because raising a Fraction to a Fraction exponent (a non-integer power) always returns float, not Fraction -- we confirmed any Fraction added to that result afterward is coerced to float too, silently ending the exact arithmetic from that point on.

Does Fraction ** int stay exact in Python?

Yes -- we measured Fraction(9,1) ** 2 returning the exact Fraction 81, not a float. Only a Fraction (non-integer) exponent triggers the fallback to float; integer exponents preserve the Fraction type.

How do I compute an exact square root of a Fraction without losing precision?

Python's fractions module doesn't provide one via ** -- we measured Fraction(9,1) ** Fraction(1,2) returning float(3.0) rather than Fraction(3,1). Check if the numerator and denominator are both perfect squares (e.g. with math.isqrt) and build the exact Fraction yourself if you need to stay exact.

Is there a difference between Fraction(4,1) ** 0.5 and Fraction(4,1) ** Fraction(1,2)?

No -- we measured both returning the same float result (2.0). Any non-integer exponent, whether a plain float or a Fraction, makes Fraction's ** fall back to floating-point power and return a float.

Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in fractions module: raised several Fractions to Fraction exponents whose exact results are themselves rational (e.g. a perfect square root), compared to raising the same Fractions to int exponents, and checked the type of each result plus what happens when it's used in further Fraction arithmetic. PlainHeaders is our extension; Python's fractions module is built in.