statistics: covariance() Always Returns float, Unlike variance() (tested)
statistics.mean() and variance() are documented to preserve exact types like Fraction and Decimal. We measured whether the newer covariance(), correlation(), and linear_regression() functions (added in Python 3.10) follow the same rule, on data where exactness is fully achievable.
1. variance() stays an exact Fraction; covariance() on the same kind of data returns float
from fractions import Fraction
import statistics as st
x = [Fraction(1, 3), Fraction(2, 3), Fraction(1, 1)]
print(st.variance(x), type(st.variance(x)))
print(st.mean(x), type(st.mean(x)))
1/9
2/3
Measured: variance() and mean() on a list of Fraction values return exact Fraction results -- 1/9 and 2/3, with no rounding, because every intermediate step (sums, differences, squaring) stays in exact rational arithmetic.
2. covariance() on Fraction input discards that exactness, with no sqrt involved
from fractions import Fraction
import statistics as st
x = [Fraction(1, 3), Fraction(2, 3), Fraction(1, 1)]
y = [Fraction(1, 7), Fraction(2, 7), Fraction(3, 7)]
print(st.covariance(x, y), type(st.covariance(x, y)))
0.047619047619047616
Measured: covariance() on the equivalent Fraction data returns a float -- 0.047619047619047616, a repeating decimal approximation of the exact value Fraction(1, 21). Unlike stdev(), which is documented to always return float because taking a square root makes an exact rational result impossible in general, covariance() has no such mathematical excuse: its formula is pure sums, products, and division by a count, every one of which variance() keeps exact on the same kind of input.
3. correlation() and linear_regression() both have the same unconditional float coercion
from fractions import Fraction
import statistics as st
x = [Fraction(1), Fraction(2), Fraction(3)]
y = [Fraction(2), Fraction(4), Fraction(6)]
print(st.correlation(x, y), type(st.correlation(x, y)))
r = st.linear_regression(x, y)
print(r, type(r.slope))
1.0
LinearRegression(slope=2.0, intercept=0.0)
Measured: both correlation() and linear_regression() return plain float for every field, even on this perfectly exact, proportional Fraction data (y = 2x exactly). All three of the newer statistics functions (3.10+) coerce through float internally and always return float, regardless of input type -- a type-preservation guarantee that holds for mean()/variance()/median() but not for this newer trio, which is easy to miss since they share the same module and calling convention.
Frequently asked questions
Does statistics.covariance() preserve Fraction precision like variance() does?
No -- we measured covariance() on Fraction input returning a plain float (0.047619047619047616), while variance() on the equivalent Fraction data returns an exact Fraction (1/9).
Why does covariance() return float when it doesn't need a square root?
It's an implementation choice, not a mathematical requirement -- covariance()'s formula is sums, products, and division, all of which variance() keeps exact on Fraction input. covariance(), correlation(), and linear_regression() all coerce through float unconditionally regardless of whether exactness would be achievable.
Do correlation() and linear_regression() also lose Fraction exactness?
Yes -- we measured both returning plain float for every field, even on perfectly exact, proportional Fraction data (y = 2x exactly), where an exact Fraction result would have been possible.
Which statistics functions preserve exact types like Fraction and Decimal?
We measured mean() and variance() preserving Fraction exactly. The newer functions added in Python 3.10 -- covariance(), correlation(), and linear_regression() -- always return float instead, regardless of input type.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in statistics module: computed variance() and covariance() on the same Fraction data and compared result types. PlainHeaders is our extension; Python's statistics module is built in.