Rational — Arbitrary-Precision Rational Numbers
Contents
Overview
Rational is the arbitrary-precision rational number type in calx.
Internally it stores a pair of (numerator Int, denominator Int) , representing a value $x$ as:
$$x = \frac{p}{q}, \quad q > 0, \quad \gcd(p, q) = 1$$
The denominator is always positive, and the numerator and denominator are always kept in reduced form.
A zero denominator is treated as NaN.
Arbitrary precision — Both numerator and denominator are Int, so there is no limit on the number of digits
Automatic reduction — After every operation, the result is reduced by GCD and kept in canonical form
NaN-safe — Division by zero returns NaN instead of crashing
Mixed operations with Int/int — Expressions like Rational + Int and Rational * int work naturally
Constructors
Signature Description
Rational()Default construction. Value is 0/1
Rational(int num, int den = 1)Construct from int numerator/denominator (automatically reduced)
Rational(const Int& num)Construct from Int (denominator = 1)
Rational(const Int& num, const Int& den, bool doReduce = true)Construct from Int numerator/denominator
Rational(Int&& num, Int&& den, bool doReduce = true)Move version
Rational(std::string_view str, int base = 10)Construct from string in "p/q" format
Rational(double value)Convert a double to an exact rational number
Rational(float value)Convert a float to an exact rational number
Rational(const Float& value)Convert a multi-precision float to an exact rational number
Specifying doReduce = false skips reduction (use when the caller guarantees the fraction is already in reduced form).
Accessors
Member Function Description
const Int& numerator() constReturns the numerator
const Int& denominator() constReturns the denominator (always positive)
friend void swap(Rational& a, Rational& b) noexceptSwaps two Rational objects
Arithmetic Operators
Basic Arithmetic
Operator Description
Rational + RationalAddition ($\frac{a}{b} + \frac{c}{d} = \frac{ad+bc}{bd}$, reduced)
Rational - RationalSubtraction
Rational * RationalMultiplication ($\frac{a}{b} \times \frac{c}{d} = \frac{ac}{bd}$, reduced)
Rational / RationalDivision ($\frac{a}{b} \div \frac{c}{d} = \frac{ad}{bc}$, reduced)
Rational % RationalRemainder
Mixed operations with Int and int are fully supported:
Rational + Int, Int + Rational
Rational * int, int * Rational
Compound assignment: +=, -=, *=, /=
Code Example
Rational a(1, 3), b(1, 6);
Rational c = a + b; // 1/2
Rational d = a * b; // 1/18
Rational e = a / b; // 2
Rational f = a - b; // 1/6
Other Operations
Operation Description
-rNegation
++r, r++Increment
--r, r--Decrement
r.pow(n)$r^n$ (int exponent)
pow(r, e)$r^e$ (Int exponent)
r << n$r \times 2^n$
r >> n$r / 2^n$
Comparison Operators
Supports C++20 three-way comparison (<=>). Returns std::partial_ordering (to account for NaN).
Comparison Description
Rational <=> RationalThree-way comparison
Rational == RationalEquality comparison
Rational <=> IntComparison with Int
Rational <=> intComparison with int
State Queries
Member Function Description
isZero()Whether the value is 0
isNonZero()Whether the value is non-zero
isPositive()Whether the value is positive
isNegative()Whether the value is negative
isNonPositive()Whether the value is ≤ 0
isNonNegative()Whether the value is ≥ 0
isOne()Whether the value is 1
isInteger()Whether the denominator is 1 (i.e., an integer value)
isNaN()Whether the value is NaN
reduce()Manually reduce and normalize the fraction. Use this when you skipped reduction with doReduce=false in the constructor. Returns true if the value changed
Math Functions
Function Description
abs(x)Absolute value $|x|$
inv(x)Reciprocal $1/x$
square(x)$x^2$
sgn(x)Sign ($-1, 0, 1$)
floor(x)$\lfloor x \rfloor$ (returns Int)
ceil(x)$\lceil x \rceil$ (returns Int)
trunc(x)Truncation toward zero (returns Int)
round(x)Rounding to nearest integer (returns Int)
frac(x)Fractional part $x - \lfloor x \rfloor$
height(x)Height $\max(|p|, |q|)$
gcd(x, y)GCD of rational numbers
mediant(a, b)Mediant $\frac{p_a + p_b}{q_a + q_b}$
r.doubled()$2r$
r.halved()$r/2$
r.reciprocal()Reciprocal $q/p$. $O(1)$. Reciprocal of zero returns NaN
conj(x)Conjugate (returns itself for real rationals; exists for compatibility with Complex<Rational>)
Continued Fractions
Function Description
r.toContinuedFraction()Returns the continued fraction expansion $[a_0; a_1, a_2, \ldots]$
Rational::fromContinuedFraction(cf)Reconstructs a Rational from a continued fraction
Rational r(355, 113);
auto cf = r.toContinuedFraction(); // [3; 7, 16]
Rational r2 = Rational::fromContinuedFraction(cf); // 355/113
Number-Theoretic Functions
Function Description
harmonicNumber(n)Harmonic number $H_n = 1 + \frac{1}{2} + \cdots + \frac{1}{n}$
dedekindSum(h, k)Dedekind sum $s(h, k)$
reconstructRational(a, m, N, D)Reconstruct $p/q$ from $a \bmod m$ ($|p| \le N, 0 < q \le D$)
mod(x, m)Rational mod: $\frac{p}{q} \bmod m = p \cdot q^{-1} \bmod m$
Rational Enumeration
Function Description
nextMinimal(x)Next positive rational in Stern-Brocot order
nextCalkinWilf(x)Next positive rational in the Calkin-Wilf sequence
fareyNeighbors(x, Q)Left and right neighbors in the Farey sequence $F_Q$
simplestBetween(a, b)Rational of smallest height in the open interval $(a, b)$
Mathematical Constants
The following constants are computed exactly as Rational values. Computed values are stored in a thread-safe static cache.
Function Description
bernoulli(n)Bernoulli number $B_n$ (standard recurrence)
stirlingCoefficient(k)Stirling approximation coefficient $c_k$
Rational b0 = bernoulli(0); // 1
Rational b1 = bernoulli(1); // -1/2
Rational b2 = bernoulli(2); // 1/6
Rational b4 = bernoulli(4); // -1/30
Rational b6 = bernoulli(6); // 1/42
Conversion
Function Description
toDouble()Convert to double
toFloat()Convert to float
toMpFloat(precision)Convert to Float (with specified precision)
toString(base)String in "p/q" format
toDecimal(digits)Decimal string with specified number of digits
explicit operator int()Convert to int (truncated)
explicit operator double()Convert to double
Rational& operator=(double value)Assignment from double
Rational& operator=(float value)Assignment from float
Code Example
Rational r(22, 7);
double d = r.toDouble(); // 3.14285...
std::string s = r.toString(); // "22/7"
bool b = (Rational(1,3) < Rational(1,2)); // true
Stream I/O
Rational r(22, 7);
std::cout << r; // Output: 22/7
Rational s;
std::cin >> s; // Input: "3/4" -> Rational(3, 4)
Usage Example
#include <math/core/mp/Rational.hpp>
#include <iostream>
using namespace calx;
int main() {
// Basic arithmetic (automatically reduced)
Rational a(1, 3); // 1/3
Rational b(1, 6); // 1/6
std::cout << a + b << std::endl; // 1/2
// Bernoulli numbers
for (int n = 0; n <= 10; n += 2)
std::cout << "B(" << n << ") = " << bernoulli(n) << std::endl;
// Continued fraction expansion
Rational pi_approx(355, 113);
auto cf = pi_approx.toContinuedFraction(); // [3; 7, 16]
// Harmonic number
Rational h10 = harmonicNumber(10); // 7381/2520
std::cout << "H(10) = " << h10 << " = " << h10.toDecimal(15) << std::endl;
// NaN safety
Rational nan = Rational(1, 0);
std::cout << nan << std::endl; // NaN
}