Repository: sympy/sympy

Issue:
Weird behaviour of sympy.nroots with complex numbers
Hello,

sympy.nroots does not seem to respect the required precision when the root is complex (please see the picture below for a minimal example).

Asking for a high-precision real root, together with setting mpmath.mp.dps seems to fix the issue.
Perhaps a less hacky fix may be preferable.

![SympyNrootWithComplexNumbers](https://user-images.githubusercontent.com/24232918/181993456-99b40c3b-eea1-4afb-b1f4-45adcc20f8c3.png)

Also, inverting the order of cell [3] and [4] does not fix the result of cell [3].

Code from screenshot:
```
import sympy
import mpmath
sympy.__version__
> '1.10.1'
sympy.nroots("x + 3", n=300)  # nice 300 digit result
> [-3.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]
sympy.nroots(f"x + 3.{'0' * 50}1j", n=300, maxsteps=500)  # lost precision: there should be a 1 after 50 zeros
> [-3.0*I]
mpmath.mp.dps = 300  # without this the (hacky) fix in the next cell does not work
sympy.nroots(f"x - 3.{'0' * 290}1", n=300, maxsteps=500)  # asking for a real root here with 300 digits then fixes the following call
> [3.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100208418]
sympy.nroots(f"x + 3.{'0' * 50}1j", n=300, maxsteps=500)  # nice high precision result recovered
> [-3.000000000000000000000000000000000000000000000000001002286766284573367302701175181805704555698830039393261735726559560149490370173884501436845084754168055951595306396484375*I]
```


Discussion hints:

Solution patch:
diff --git a/sympy/polys/polytools.py b/sympy/polys/polytools.py
index 69051cd28f..11b9dd3435 100644
--- a/sympy/polys/polytools.py
+++ b/sympy/polys/polytools.py
@@ -3712,11 +3712,12 @@ def nroots(f, n=15, maxsteps=50, cleanup=True):
         else:
             coeffs = [coeff.evalf(n=n).as_real_imag()
                     for coeff in f.all_coeffs()]
-            try:
-                coeffs = [mpmath.mpc(*coeff) for coeff in coeffs]
-            except TypeError:
-                raise DomainError("Numerical domain expected, got %s" % \
-                        f.rep.dom)
+            with mpmath.workdps(n):
+                try:
+                    coeffs = [mpmath.mpc(*coeff) for coeff in coeffs]
+                except TypeError:
+                    raise DomainError("Numerical domain expected, got %s" % \
+                            f.rep.dom)
 
         dps = mpmath.mp.dps
         mpmath.mp.dps = n


Test patch:
diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py
index 0313d12c8d..a4096447ce 100644
--- a/sympy/polys/tests/test_polytools.py
+++ b/sympy/polys/tests/test_polytools.py
@@ -3202,6 +3202,12 @@ def test_nroots():
         '1.7 + 2.5*I]')
     assert str(Poly(1e-15*x**2 -1).nroots()) == ('[-31622776.6016838, 31622776.6016838]')
 
+    # https://github.com/sympy/sympy/issues/23861
+
+    i = Float('3.000000000000000000000000000000000000000000000000001')
+    [r] = nroots(x + I*i, n=300)
+    assert abs(r + I*i) < 1e-300
+
 
 def test_ground_roots():
     f = x**6 - 4*x**4 + 4*x**3 - x**2