Repository: sympy/sympy

Issue:
Wrong result from floor().evalf()
Computation of `frac(1169809367327212570704813632106852886389036911/(pi/2)).evalf()` is wrong. It seems to be coming from floor rounding up. 

```py
>>> n = 1169809367327212570704813632106852886389036911
>>> (n/(pi/2)).evalf()
7.44723773141314e+44
>>> frac(n/(pi/2)).evalf()
-1.35186796244200e-46
>>> frac(n/(pi/2)).evalf(1000)
-0.0000000000000000000000000000000000000000000001351867962442000401008728145888546483321446030864887022443940287194780615993835637342483498767911434917489502110982992819265464985749696754683123627743678861771451915449441051478668292996323677686365388779412619735119801773968567820011094032563665978687180928661858946201027615506756505069763448198525496763216191757328086749471839366720416146772374081242021865051183367802440181189193685259272004936979661297311890761105495377749194158661999919877164536037376317643131953866288010782228115971557921849226634254645633475875233163237046084416523237844579932656980807300374078518788938452018328577301739998847698987226245652583275769485245784962092841469396807216663537547393562300455603107595063787361610258797658928069592651540018601708386203226763763851943744891298228425798297698451035672590474624778574511314810780376369855321035022245596091552072107522977124876749523071255736527459703870988453475793396972936802100590240488838896549220959824508678902191633865798366182425390167142880067498717612
>>> (n/(pi/2)).evalf(1000)
744723773141314414542111064094745678855643068.9999999999999999999999999999999999999999999998648132037557999598991271854111453516678553969135112977556059712805219384006164362657516501232088565082510497889017007180734535014250303245316876372256321138228548084550558948521331707003676322313634611220587380264880198226031432179988905967436334021312819071338141053798972384493243494930236551801474503236783808242671913250528160633279583853227625918757978134948816632197559818810806314740727995063020338702688109238894504622250805841338000080122835463962623682356868046133711989217771884028442078150773365745354366524124766836762953915583476762155420067343019192699625921481211061547981671422698260001152301012773754347416724230514754215037907158530603192783336462452606437699544396892404936212638389741202341071930407348459981398291613796773236236148056255108701771574201702301548964327409525375221425488685189219623630144678964977754403908447927892477022875123250476928744263472540296129011546524206603027
>>> floor(n/(pi/2)).evalf(1000)
744723773141314414542111064094745678855643069.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
```

See https://twitter.com/robinhouston/status/1296499536794460160

Discussion:

Patch:
diff --git a/sympy/core/evalf.py b/sympy/core/evalf.py
index 812e9de5f8..a91c141974 100644
--- a/sympy/core/evalf.py
+++ b/sympy/core/evalf.py
@@ -353,8 +353,8 @@ def get_integer_part(expr, no, options, return_ints=False):
     # positive or negative (which may fail if very close).
     def calc_part(re_im, nexpr):
         from sympy.core.add import Add
-        n, c, p, b = nexpr
-        is_int = (p == 0)
+        _, _, exponent, _ = nexpr
+        is_int = exponent == 0
         nint = int(to_int(nexpr, rnd))
         if is_int:
             # make sure that we had enough precision to distinguish
@@ -369,9 +369,9 @@ def calc_part(re_im, nexpr):
                     re_im, size, options)
                 assert not iim
                 nexpr = ire
-                n, c, p, b = nexpr
-                is_int = (p == 0)
-                nint = int(to_int(nexpr, rnd))
+            nint = int(to_int(nexpr, rnd))
+            _, _, new_exp, _ = ire
+            is_int = new_exp == 0
         if not is_int:
             # if there are subs and they all contain integer re/im parts
             # then we can (hopefully) safely substitute them into the
diff --git a/sympy/functions/elementary/integers.py b/sympy/functions/elementary/integers.py
index 2b4d32f217..845e70a742 100644
--- a/sympy/functions/elementary/integers.py
+++ b/sympy/functions/elementary/integers.py
@@ -156,8 +156,6 @@ def _eval_rewrite_as_ceiling(self, arg, **kwargs):
     def _eval_rewrite_as_frac(self, arg, **kwargs):
         return arg - frac(arg)
 
-
-
     def __le__(self, other):
         other = S(other)
         if self.args[0].is_real:
@@ -214,11 +212,13 @@ def __lt__(self, other):
 
         return Lt(self, other, evaluate=False)
 
+
 @dispatch(floor, Expr)
 def _eval_is_eq(lhs, rhs): # noqa:F811
    return is_eq(lhs.rewrite(ceiling), rhs) or \
         is_eq(lhs.rewrite(frac),rhs)
 
+
 class ceiling(RoundFunction):
     """
     Ceiling is a univariate function which returns the smallest integer
@@ -292,8 +292,6 @@ def _eval_is_positive(self):
     def _eval_is_nonpositive(self):
         return self.args[0].is_nonpositive
 
-
-
     def __lt__(self, other):
         other = S(other)
         if self.args[0].is_real:
@@ -350,10 +348,12 @@ def __le__(self, other):
 
         return Le(self, other, evaluate=False)
 
+
 @dispatch(ceiling, Basic)  # type:ignore
 def _eval_is_eq(lhs, rhs): # noqa:F811
     return is_eq(lhs.rewrite(floor), rhs) or is_eq(lhs.rewrite(frac),rhs)
 
+
 class frac(Function):
     r"""Represents the fractional part of x
 
@@ -445,8 +445,6 @@ def _eval_rewrite_as_floor(self, arg, **kwargs):
     def _eval_rewrite_as_ceiling(self, arg, **kwargs):
         return arg + ceiling(-arg)
 
-
-
     def _eval_is_finite(self):
         return True
 
@@ -522,6 +520,7 @@ def _value_one_or_more(self, other):
             if other.is_integer and other.is_positive:
                 return S.true
 
+
 @dispatch(frac, Basic)  # type:ignore
 def _eval_is_eq(lhs, rhs): # noqa:F811
     if (lhs.rewrite(floor) == rhs) or \


Test patch:
diff --git a/sympy/core/tests/test_evalf.py b/sympy/core/tests/test_evalf.py
index dc3a1663ca..6a926830c2 100644
--- a/sympy/core/tests/test_evalf.py
+++ b/sympy/core/tests/test_evalf.py
@@ -1,6 +1,6 @@
 from sympy import (Abs, Add, atan, ceiling, cos, E, Eq, exp, factor,
     factorial, fibonacci, floor, Function, GoldenRatio, I, Integral,
-    integrate, log, Mul, N, oo, pi, Pow, product, Product,
+    integrate, log, Mul, N, oo, pi, Pow, product, Product, tan,
     Rational, S, Sum, simplify, sin, sqrt, sstr, sympify, Symbol, Max, nfloat, cosh, acosh, acos)
 from sympy.core.numbers import comp
 from sympy.core.evalf import (complex_accuracy, PrecisionExhausted,
@@ -262,6 +262,16 @@ def test_evalf_integer_parts():
     assert float((floor(1.5, evaluate=False)+1/9).evalf()) == 1 + 1/9
     assert float((floor(0.5, evaluate=False)+20).evalf()) == 20
 
+    # issue 19991
+    n = 1169809367327212570704813632106852886389036911
+    r = 744723773141314414542111064094745678855643068
+
+    assert floor(n / (pi / 2)) == r
+    assert floor(80782 * sqrt(2)) == 114242
+
+    # issue 20076
+    assert 260515 - floor(260515/pi + 1/2) * pi == atan(tan(260515))
+
 
 def test_evalf_trig_zero_detection():
     a = sin(160*pi, evaluate=False)