Skip to content

Commit 7e5d1d8

Browse files
authored
gh-72902: Speedup Fraction.from_decimal/float in typical cases (GH-133251)
1 parent 43c60ec commit 7e5d1d8

2 files changed

Lines changed: 13 additions & 10 deletions

File tree

Lib/fractions.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -339,24 +339,24 @@ def from_float(cls, f):
339339
Beware that Fraction.from_float(0.3) != Fraction(3, 10).
340340
341341
"""
342+
if isinstance(f, float):
343+
return cls._from_coprime_ints(*f.as_integer_ratio())
342344
if isinstance(f, numbers.Integral):
343345
return cls(f)
344-
elif not isinstance(f, float):
345-
raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
346-
(cls.__name__, f, type(f).__name__))
347-
return cls._from_coprime_ints(*f.as_integer_ratio())
346+
raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
347+
(cls.__name__, f, type(f).__name__))
348348

349349
@classmethod
350350
def from_decimal(cls, dec):
351351
"""Converts a finite Decimal instance to a rational number, exactly."""
352352
from decimal import Decimal
353+
if isinstance(dec, Decimal):
354+
return cls._from_coprime_ints(*dec.as_integer_ratio())
353355
if isinstance(dec, numbers.Integral):
354-
dec = Decimal(int(dec))
355-
elif not isinstance(dec, Decimal):
356-
raise TypeError(
357-
"%s.from_decimal() only takes Decimals, not %r (%s)" %
358-
(cls.__name__, dec, type(dec).__name__))
359-
return cls._from_coprime_ints(*dec.as_integer_ratio())
356+
dec = int(dec)
357+
return cls._from_coprime_ints(*dec.as_integer_ratio())
358+
raise TypeError("%s.from_decimal() only takes Decimals, not %r (%s)" %
359+
(cls.__name__, dec, type(dec).__name__))
360360

361361
@classmethod
362362
def _from_coprime_ints(cls, numerator, denominator, /):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Optimize (~x1.4 speedup) :meth:`fractions.Fraction.from_decimal` and
2+
:meth:`fractions.Fraction.from_float` for :class:`~decimal.Decimal` and
3+
:class:`float` inputs, respectively. Patch by Sergey B Kirpichev.

0 commit comments

Comments
 (0)