Plate 77
fractions.Fraction vs float: Localhost Lab
Hands-on fractions.Fraction vs float for exact ratios: real ops/s and exactness checks, measured on Linux localhost today in this hands-on lab for SREs.
Aditya Challa4 min read
Intro — what this post promises
Exact rational math with fractions.Fraction vs float (and a Decimal reference arm). This lab reports ops/s on Linux localhost, plus exactness checks for ratios that cancel in theory and diverge in binary float.
Related links:
- statistics quantiles vs manual localhost lab
- random choices vs sample localhost lab
- graphlib topo vs manual localhost lab
- functools cache vs lru localhost lab
- tomllib vs json localhost lab
- path glob vs fnmatch localhost lab
- itertools batched vs chunk localhost lab
- exitstack vs nested with localhost lab
Lab honesty (1 Oct 2026 IST): Python 3.13.5 on this Linux box. Affiliates: 0. Differentiates from Decimal-vs-float sum (lab 85) — focus here is Fraction rationals and exact canceling products, not money decimals.
Verdict up front: float sum 0.1×50 k ~119415247 ops/s; Decimal ~20714012; Fraction ~2420034. Ratio product ∏ i/(i+1): float ~30498219 ops/s vs Fraction ~1311467 — Fraction stays exact (1/5001).
Arms
| Arm | Pattern |
|---|---|
sum([0.1]*n) | binary float tenths |
sum([Fraction(1,10)]*n) | exact tenths |
sum([Decimal("0.1")]*n) | decimal reference |
| ∏ i/(i+1) float vs Fraction | canceling ratios |
| Fraction(float) vs Fraction("0.1") | construction paths |
Each arm measures wall time with time.perf_counter over seven rounds and reports p50 ops/s so one noisy sample cannot dominate the lead table.
Lab topology
Script: lab-evidence/122-fractions-vs-float/results/run_lab.py. Same machine, same interpreter — no invented timings.
Lead table (p50 ops/s)
| Arm | ops/s |
|---|---|
| sum float 0.1 | 119415247 |
| sum Decimal "0.1" | 20714012 |
| sum Fraction 1/10 | 2420034 |
| product ratio float | 30498219 |
| product ratio Fraction | 1311467 |
| Fraction from float accum | 710385 |
| Fraction from str accum | 524856 |
Float leads throughput. Fraction pays for arbitrary-precision gcd work on every multiply/add.
Exactness
- Ratio product: Fraction
1/5001; float0.00019996000799840023(last bits ≠float(Fraction)=0.0001999600079984003). - Prefer
Fraction(1, 10)orFraction("0.1")— notFraction(0.1), which freezes binary residue into a huge numerator/denominator.
On this run, sum([0.1]*50000) may print as a tidy 5000.0. That cosmetic print does not make float a rational type; the canceling product still drifts from exact 1/5001.
Construction checklist
| Goal | Construct |
|---|---|
| Exact tenth | Fraction(1, 10) / Fraction("0.1") |
| From binary float | Fraction(x).limit_denominator() |
| Money / currency | prefer Decimal (see lab 85) |
| Hot telemetry means | stay on float |
Reading it for SRE work
- Billing rates, mix ratios, probability fractions that must cancel cleanly → Fraction.
- Hot path averages and gauges → float, accept binary error and document it.
- Never build Fraction from a polluted float and expect exact decimal tenths.
- Lab 85 already covered Decimal sums; this post is rational exactness under load.
If you only need “close enough” for dashboards, float’s ~119415247 ops/s is the right tool. If auditors ask for exact 1/5001, Fraction’s slower path is the one that answers without hand-waving.
Pitfalls
Fraction(0.1)capturing binary float residue.- Unbounded Fraction growth in long products without
limit_denominator. - Using Fraction in a numpy/GPU path by accident.
- Comparing speed alone without stating exactness goals.
- Treating a pretty printed float total as proof of exactness.
Reproduce
Evidence: summary.json, summary.txt under lab-evidence/122-fractions-vs-float/results/.
Limits
One Linux box, CPython 3.13.5, pure-Python Fraction. Not mpmath, not GPU reductions, not multi-process.
Takeaway
Float wins throughput (~119415247 ops/s on the 0.1 sum); Fraction is slower (~2420034) but keeps exact rationals like 1/5001. Use Fraction when exact ratios matter; use float when speed dominates and binary error is acceptable.
Lab evidence
What I found running this
Ran the package lab on Linux localhost with CPython 3.13.5 on 1 Oct 2026 IST. Benchmarked seven rounds at p50: float, Decimal, and Fraction sums plus canceling products. Verified the exact Fraction result 1/5001 and float drift; affiliates 0.
Related links
Plate 34
ast.literal_eval vs json.loads: Localhost Lab
1 Oct 2026
Plate 68
gc.collect Cost Empty vs Cycles: Localhost Lab
Hands-on gc.collect cost empty vs cyclic garbage lab: real collect latency plus reclaim counts, measured on Linux localhost today in this lab for SREs.
Observability & SRE · 1 Oct 2026
Plate 76
html.parser vs regex Tag Strip: Localhost Lab
1 Oct 2026