Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/sage/rings/qqbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -5741,11 +5741,11 @@ def _floor_ceil(self, method):
....: AA(0), AA(1), AA(-1), AA(1/2), AA(-1/2)]]
[[0, 1, 1, 0], [-1, 0, -1, 0], [1, 2, 1, 1], [-2, -1, -1, -1],
[17, 18, 18, 17], [0, 0, 0, 0], [1, 1, 1, 1], [-1, -1, -1, -1],
[0, 1, 1, 0], [-1, 0, -1, 0]]
[0, 1, 0, 0], [-1, 0, 0, 0]]
sage: [[z.floor(), z.ceil(), z.trunc()] for z in [two, a*b]] # long time
[[2, 2, 2], [0, 1, 0]]
sage: [one_half.round(), (-one_half).round()] # long time
[1, -1]
[0, 0]
"""
for i in itertools.count():
candidate = method(self._value.lower())
Expand Down Expand Up @@ -5806,9 +5806,9 @@ def round(self):
sage: AA(sqrt(2)).round() # needs sage.symbolic
1
sage: AA(1/2).round()
1
0
sage: AA(-1/2).round()
-1
0
"""
return self._floor_ceil(lambda x: x.round())

Expand Down
24 changes: 9 additions & 15 deletions src/sage/rings/real_mpfi.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
r"""
Arbitrary precision real intervals using MPFI
Arbitrary precision real intervals using MPFR

AUTHORS:

Expand Down Expand Up @@ -3123,9 +3123,9 @@ cdef class RealIntervalFieldElement(RingElement):

sage: r = RIF(2.5, 3.5).round()
sage: r
4.?
3.?
sage: r.lower()
3.00000000000000
2.00000000000000
sage: r.upper()
4.00000000000000
"""
Expand Down Expand Up @@ -3478,28 +3478,22 @@ cdef class RealIntervalFieldElement(RingElement):
sage: RIF(-pi).unique_round() # needs sage.symbolic
-3
sage: (RIF(4.5).unique_round(), RIF(-4.5).unique_round())
(5, -5)
(4, -4)

TESTS::

sage: RIF(-1/2, -1/3).unique_round()
Traceback (most recent call last):
...
ValueError: interval does not have a unique round (nearest integer)
0
sage: RIF(-1/2, 1/3).unique_round()
Traceback (most recent call last):
...
ValueError: interval does not have a unique round (nearest integer)
0
sage: RIF(-1/3, 1/3).unique_round()
0
sage: RIF(-1/2, 0).unique_round()
Traceback (most recent call last):
...
ValueError: interval does not have a unique round (nearest integer)
0
sage: RIF(1/2).unique_round()
1
0
sage: RIF(-1/2).unique_round()
-1
0
sage: RIF(0).unique_round()
0
"""
Expand Down
34 changes: 30 additions & 4 deletions src/sage/rings/real_mpfr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3033,7 +3033,11 @@ cdef class RealNumber(sage.structure.element.RingElement):
def round(self):
"""
Round ``self`` to the nearest representable integer, rounding halfway
cases away from zero.
cases to even (banker's rounding).

This matches the behavior of Python's built-in ``round()`` function
for floats (Python 3+), and Sage's ``Rational.round()`` with default
mode.

.. NOTE::

Expand All @@ -3044,14 +3048,36 @@ cdef class RealNumber(sage.structure.element.RingElement):
sage: RR(0.49).round()
0
sage: RR(0.5).round()
1
0
sage: RR(-0.49).round()
0
sage: RR(-0.5).round()
-1
0
sage: RR(1.5).round()
2
sage: RR(2.5).round()
2
sage: RR(-1.5).round()
-2
sage: RR(-2.5).round()
-2

This uses round-to-even (banker's rounding) for tie cases, matching
Python 3 behavior and IEEE 754 default rounding::

sage: [RR(n + 0.5).round() for n in range(-5, 6)]
[-4, -4, -2, -2, 0, 0, 2, 2, 4, 4, 6]

Compare with ``Rational.round()``::

sage: RR(5/2).round() == QQ(5/2).round()
True
sage: RR(-7/2).round() == QQ(-7/2).round()
True
"""
cdef RealNumber x = self._new()
mpfr_round(x.value, self.value)
# Use mpfr_rint with MPFR_RNDN (round to nearest, ties to even)
mpfr_rint(x.value, self.value, MPFR_RNDN)
return x.integer_part()

def floor(self):
Expand Down
Loading