Skip to content

Commit 5ac7043

Browse files
lisroachrhettinger
authored andcommitted
bpo-33073: Adding as_integer_ratio to ints. (GH-8750)
1 parent 83df50e commit 5ac7043

File tree

8 files changed

+108
-2
lines changed

8 files changed

+108
-2
lines changed

Doc/library/stdtypes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,14 @@ class`. In addition, it provides a few more methods:
537537

538538
.. versionadded:: 3.2
539539

540+
.. method:: int.as_integer_ratio()
541+
542+
Return a pair of integers whose ratio is exactly equal to the original
543+
integer and with a positive denominator. The integer ratio of integers
544+
(whole numbers) is always the integer as the numerator and ``1`` as the
545+
denominator.
546+
547+
.. versionadded:: 3.8
540548

541549
Additional Methods on Float
542550
---------------------------

Doc/whatsnew/3.8.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ Other Language Changes
9191
was lifted.
9292
(Contributed by Serhiy Storchaka in :issue:`32489`.)
9393

94+
* The ``int`` type now has a new ``as_integer_ratio`` method compatible
95+
with the existing ``float.as_integer_ratio`` method.
96+
(Contributed by Lisa Roach in :issue:`33073`.)
97+
9498
* Added support of ``\N{name}`` escapes in :mod:`regular expressions <re>`.
9599
(Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
96100

Lib/test/test_doctest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ def non_Python_modules(): r"""
665665
True
666666
>>> real_tests = [t for t in tests if len(t.examples) > 0]
667667
>>> len(real_tests) # objects that actually have doctests
668-
8
668+
9
669669
>>> for t in real_tests:
670670
... print('{} {}'.format(len(t.examples), t.name))
671671
...
@@ -675,6 +675,7 @@ def non_Python_modules(): r"""
675675
2 builtins.float.hex
676676
1 builtins.hex
677677
1 builtins.int
678+
3 builtins.int.as_integer_ratio
678679
2 builtins.int.bit_length
679680
1 builtins.oct
680681

Lib/test/test_long.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import sys
55

6+
import enum
67
import random
78
import math
89
import array
@@ -1349,6 +1350,37 @@ def test_shift_bool(self):
13491350
self.assertEqual(type(value << shift), int)
13501351
self.assertEqual(type(value >> shift), int)
13511352

1353+
def test_as_integer_ratio(self):
1354+
tests = [10, 0, -10, 1]
1355+
for value in tests:
1356+
numerator, denominator = value.as_integer_ratio()
1357+
self.assertEqual((numerator, denominator), (value, 1))
1358+
self.assertIsInstance(numerator, int)
1359+
self.assertIsInstance(denominator, int)
1360+
1361+
def test_as_integer_ratio_maxint(self):
1362+
x = sys.maxsize + 1
1363+
self.assertEqual(x.as_integer_ratio()[0], x)
1364+
1365+
def test_as_integer_ratio_bool(self):
1366+
self.assertEqual(True.as_integer_ratio(), (1, 1))
1367+
self.assertEqual(False.as_integer_ratio(), (0, 1))
1368+
self.assertEqual(type(True.as_integer_ratio()[0]), int)
1369+
self.assertEqual(type(False.as_integer_ratio()[0]), int)
1370+
1371+
def test_as_integer_ratio_int_enum(self):
1372+
class Foo(enum.IntEnum):
1373+
X = 42
1374+
self.assertEqual(Foo.X.as_integer_ratio(), (42, 1))
1375+
self.assertEqual(type(Foo.X.as_integer_ratio()[0]), int)
1376+
1377+
def test_as_integer_ratio_int_flag(self):
1378+
class Foo(enum.IntFlag):
1379+
R = 1 << 2
1380+
self.assertEqual(Foo.R.as_integer_ratio(), (4, 1))
1381+
self.assertEqual(type(Foo.R.as_integer_ratio()[0]), int)
1382+
1383+
13521384

13531385
if __name__ == "__main__":
13541386
unittest.main()

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,7 @@ Juan M. Bello Rivas
13501350
Mohd Sanad Zaki Rizvi
13511351
Davide Rizzo
13521352
Anthony Roach
1353+
Lisa Roach
13531354
Carl Robben
13541355
Ben Roberts
13551356
Mark Roberts
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added as_integer_ratio to ints to make them more interoperable with floats.

Objects/clinic/longobject.c.h

Lines changed: 29 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/longobject.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5260,6 +5260,36 @@ long_is_finite(PyObject *v)
52605260
}
52615261
#endif
52625262

5263+
/*[clinic input]
5264+
int.as_integer_ratio
5265+
5266+
Return integer ratio.
5267+
5268+
Return a pair of integers, whose ratio is exactly equal to the original int
5269+
and with a positive denominator.
5270+
5271+
>>> (10).as_integer_ratio()
5272+
(10, 1)
5273+
>>> (-10).as_integer_ratio()
5274+
(-10, 1)
5275+
>>> (0).as_integer_ratio()
5276+
(0, 1)
5277+
[clinic start generated code]*/
5278+
5279+
static PyObject *
5280+
int_as_integer_ratio_impl(PyObject *self)
5281+
/*[clinic end generated code: output=e60803ae1cc8621a input=55ce3058e15de393]*/
5282+
{
5283+
if PyLong_CheckExact(self) {
5284+
return PyTuple_Pack(2, self, _PyLong_One);
5285+
} else {
5286+
PyObject *numerator = _PyLong_Copy(self);
5287+
PyObject *ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_One);
5288+
Py_DECREF(numerator);
5289+
return ratio_tuple;
5290+
}
5291+
}
5292+
52635293
/*[clinic input]
52645294
int.to_bytes
52655295
@@ -5392,6 +5422,7 @@ static PyMethodDef long_methods[] = {
53925422
#endif
53935423
INT_TO_BYTES_METHODDEF
53945424
INT_FROM_BYTES_METHODDEF
5425+
INT_AS_INTEGER_RATIO_METHODDEF
53955426
{"__trunc__", long_long_meth, METH_NOARGS,
53965427
"Truncating an Integral returns itself."},
53975428
{"__floor__", long_long_meth, METH_NOARGS,

0 commit comments

Comments
 (0)