Monday, September 04, 2023

Simplify Rational Numbers in Python

Real NumbersRationalNumbers7.922/51/2IntegersNumbers-3-2-9-7-10WholeNumbers{0, 1, 2, 3, ...}NaturalNumbers{1, 2, 3, 4, 5, ...}IrrationalNumbers√10π√2φ
The real number system: rational numbers (with natural, whole, and integers nested inside) alongside irrational numbers.

What Is a Rational Number?

A rational number is any number that can be expressed as a fraction of two integers, where the numerator is a whole number and the denominator is a non-zero integer. The decimal form of a rational number either ends (terminates) or repeats infinitely. [1, 2, 3, 4]

Key Characteristics and Forms

Rational numbers encompass a wide variety of numbers, which can always be categorized into these four main forms:

  • Integers: All whole numbers, both positive and negative, are rational because they can be written as a fraction over 1 (e.g., 5 = 5/1, -3 = -3/1).
  • Fractions: Any standard or mixed fraction where the top and bottom are integers (with a denominator not equal to 0) is rational (e.g., 3/4, 2 1/2).
  • Terminating Decimals: Decimals that eventually stop are rational because they can be converted into fractions (e.g., 0.75 = 3/4).
  • Repeating Decimals: Decimals that go on forever in a predictable, repeating pattern are rational and can be converted into fractions (e.g., 0.333... = 1/3). [3, 4, 6]

Non-Examples (Irrational Numbers)

If a number cannot be written as a fraction, and its decimal portion neither terminates nor repeats, it is considered irrational.

  • Examples: π (Pi), the square root of a non-perfect square (e.g., √2), or Euler's number (e). [1, 2, 4, 6, 7]

References

  1. Wikipedia: Rational number
  2. YouTube: What is a rational number
  3. Mathnasium: What is a rational number
  4. Math is Fun: Rational Numbers
  5. YouTube Shorts: Rational numbers
  6. Mathnasium: Rational number (term)
  7. Mometrix: Rational Numbers

How the Code Works

The notebook below converts a floating-point number into an exact fraction, and shows why the obvious approach can be surprising. It uses Python's built-in fractions.Fraction together with SymPy's Rational and nsimplify.

  • Imports: from fractions import Fraction and from sympy import Rational, nsimplify bring in both the standard-library fraction type and the symbolic-math tools.
  • Fraction(1.1) and Fraction.from_float(1.1): these return the exact value the computer actually stores for 1.1. Because 1.1 cannot be represented exactly in binary floating point, the result is a long, unexpected fraction rather than 11/10.
  • Rational(1.1): SymPy's Rational applied to a float behaves the same way, reflecting the exact binary value of the float.
  • nsimplify(1.1): nsimplify works backwards from the float to find the simple rational a human most likely meant, recovering 11/10.
  • to_frational(x): a small helper that prints both Fraction(x) and nsimplify(x) side by side, so you can compare the literal floating-point fraction against the cleaned-up rational for any input.

The takeaway: converting a float straight to a fraction preserves the floating-point rounding error, while nsimplify recovers the intended simple fraction.

to_Rational