RustPython / RustPython/pymath

Add fractions module: Rational number arithmetic

Open
#16 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
12
Forks
1
Avg merge
8m
Merged PRs (30d)
1

Description

Summary

Port Python's fractions.Fraction to Rust — arbitrary-precision rational number arithmetic.

In CPython, this is a pure Python implementation (Lib/fractions.py) that internally stores a (numerator: int, denominator: int) pair, GCD-normalized with a positive denominator.

Design

Type representation
pub struct Fraction<I> {
    numerator: I,
    denominator: I,  // always positive, coprime with numerator
}

Follow the existing _bigint feature pattern to support both num-bigint and malachite-bigint. Implement as generic over integer type or via trait bounds.

Feature flag
[features]
fractions = ["_bigint"]  # requires BigInt

Same pattern as cmath behind the complex feature.

Implementation plan

Phase 1: Core struct & construction
  • Fraction struct (numerator, denominator)
  • GCD normalization (sign normalization included: denominator always positive)
  • new(numerator, denominator) — primary constructor
  • from_integer(n) — construct from integer
  • from_float(f64) — using f64::integer_decode() or as_integer_ratio logic
  • from_coprime_ints(n, d) — direct construction from pre-normalized values (internal use)
  • String parsing: "3/4", "1.5", "1e-2", etc.
Phase 2: Arithmetic operations
  • Add, Sub, Mul, Div (Rust traits)
  • Neg, Abs
  • Floor division, modulo, divmod
  • Pow — integer exponent returns Fraction / non-integer returns f64

Arithmetic optimization: Knuth TAOCP 4.5.1 approach (pre-compute GCD in multiplication to avoid unnecessary blowup)

Phase 3: Comparison & conversion
  • Eq, Ord (cross-multiply comparison)
  • as_f64() — float conversion
  • trunc(), floor(), ceil(), round() — integer conversions
  • is_integer() — checks denominator == 1
  • as_integer_ratio() — returns (numerator, denominator) tuple
Phase 4: Special methods
  • limit_denominator(max_denominator) — best rational approximation via continued fraction algorithm
  • Hash: compatible with Python's _hash_algorithm (modular inverse based)
  • Display: "{numerator}/{denominator}" or "{numerator}" when integer
  • Format: float-style formatting (.2f, e, g, etc.)
Phase 5: Testing
  • Use the existing pyo3 proptest pattern from the project
  • Verify bit-identical results against fractions.Fraction
  • Edge cases: zero, negatives, very large numbers, float precision boundary values

Out of scope

  • Python numbers.Rational ABC (replaced by Rust traits)
  • Direct conversion with Decimal type (separate module scope)
  • Pickle/copy (Python runtime dependent)

References

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading CPython's Lib/fractions.py and the project's existing _bigint feature pattern, including cmath behind the complex feature. Review the pyo3 proptest pattern before defining the staged API and behavior. Done means the fractions feature supports the listed construction, arithmetic, conversion, formatting, and edge-case tests against fractions.Fraction.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.