fractions.Fraction.from_number() provides an explicit way to build exact rational values from compatible numeric objects. It is useful when an application must preserve a numerator-to-denominator relationship, avoid premature rounding, and make the conversion path clearer than a generic constructor call.
Understanding Fraction
The Fraction class from Python’s fractions module represents rational numbers as an integer numerator divided by an integer denominator. Unlike binary floating-point values, fractions can preserve many ratios exactly. This makes them valuable in mathematics, testing, measurement conversion, probability, scheduling ratios, and business rules where an exact relationship matters.
Review the foundations in our guides to Python data types, Python operators, and the complete Python course.
Basic usage
from fractions import Fraction
value = Fraction.from_number(5)
print(value) # 5
An integer becomes a fraction with denominator one. Existing rational objects keep their exact ratio. The method communicates that the input is already numeric rather than textual.
Converting floats
A floating-point number is stored in binary. Therefore, converting 0.1 produces the exact rational equivalent of the stored binary float, not automatically the simple decimal ratio one tenth.
from fractions import Fraction
value = Fraction.from_number(0.1)
print(value)
print(value.limit_denominator())
A large numerator and denominator are expected. Use limit_denominator() when a simpler approximation is appropriate for the domain. The official Python tutorial explains floating-point representation, while the fractions documentation describes all supported operations.
Using Decimal
Decimal is often a better source when decimal input must remain predictable. A value created as Decimal('0.125') represents exactly one eighth.
from decimal import Decimal
from fractions import Fraction
amount = Decimal('0.125')
ratio = Fraction.from_number(amount)
print(ratio) # 1/8
This approach is useful for prices, rates, and user-entered decimal values. See our Python Decimal guide for precision and rounding strategies.
Numbers versus strings
from_number() is intended for numeric objects. Text such as '3/7' or '0.25' should still be handled with the regular Fraction() constructor.
from fractions import Fraction
from_text = Fraction('3/7')
from_number = Fraction.from_number(0.25)
This separation improves readability. Text needs parsing, while a number needs conversion according to its numeric protocol.
Validation and error handling
External values should be validated before conversion. A small helper can turn low-level exceptions into a clearer domain error:
from fractions import Fraction
def as_fraction(value):
try:
return Fraction.from_number(value)
except (TypeError, ValueError) as exc:
raise ValueError(f'Invalid numeric value: {value!r}') from exc
This pattern is useful in APIs, data pipelines, command-line tools, and reusable libraries. Our guide to Python exception handling covers related practices.
Arithmetic with exact ratios
from fractions import Fraction
a = Fraction.from_number(3)
b = Fraction(1, 4)
print(a + b)
print(a * b)
print(a / b)
Results remain rational whenever possible. This behavior is helpful for musical intervals, geometric proportions, allocation rules, recipes, combinatorics, and algorithms that should not accumulate floating-point noise.
Choosing the right numeric type
Fraction is not always the best tool. Scientific arrays, machine-learning workloads, simulations, and graphics usually benefit from floating-point speed and vectorized libraries. Financial systems often prefer Decimal because business rules are expressed in decimal places and explicit rounding modes.
Choose Fraction when exact rational relationships and transparent denominators are more important than raw throughput. Avoid unnecessary conversions in performance-critical loops and benchmark realistic inputs before using fractions at scale.
Working with approximations
limit_denominator(max_denominator) can turn a complex rational representation into a useful approximation. The correct maximum depends on the problem. For a clock, denominator 60 may be meaningful; for common measurements, 8, 16, or 1000 may make sense. The method should not be used blindly because it intentionally changes the exact value.
from fractions import Fraction
raw = Fraction.from_number(3.141592653589793)
approx = raw.limit_denominator(1000)
print(approx) # 355/113
Testing strategies
Tests should cover integers, negative values, zero, Decimal inputs, floats with surprising binary representations, and unsupported objects. When approximation is used, assert an acceptable tolerance or the expected limited denominator instead of assuming a particular internal representation.
It is also useful to test round trips only when they are mathematically meaningful. Converting a fraction to float and back may not return the original fraction because the intermediate float can lose information.
Performance considerations
Fraction arithmetic normalizes values and may create large integers. Repeated operations can increase numerator and denominator size, making calculations slower than native floating-point arithmetic. Reduce the number of conversions, simplify the workflow, and use profiling before optimizing prematurely.
For bulk numeric work, consider keeping the high-volume stage in floats or arrays and using fractions only at boundaries where exact ratios are required. This hybrid approach can preserve clarity without imposing unnecessary cost throughout the application.
Practical best practices
Use integers and Decimal when a simple exact ratio is required. Document float conversions because they preserve the stored binary value. Apply limit_denominator() only when approximation is acceptable. Validate untrusted input, handle unsupported types, and define the numeric policy of the application clearly.
Prefer readable variable names such as ratio, share, or conversion_rate. A fraction communicates intent best when the surrounding code explains what the numerator and denominator mean.
Conclusion
Fraction.from_number() makes numeric-to-rational conversion explicit and readable. It preserves exact relationships where possible, clarifies the difference between numeric and textual inputs, and works well with integers, floats, and Decimal. Combined with validation, approximation limits, testing, and thoughtful type selection, it provides a reliable foundation for exact rational calculations in Python.







