This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: complex sqrt error
Type: behavior Stage:
Components: None Versions: Python 3.1, Python 3.2
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: JBernardo, mark.dickinson, vstinner
Priority: normal Keywords:

Created on 2011-03-24 02:30 by JBernardo, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (3)
msg131951 - (view) Author: João Bernardo (JBernardo) * Date: 2011-03-24 02:30
With Python 3, the ** operator is supposed to do math with complex numbers, but look what is happening:

Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> (-1)**.5
(6.123233995736766e-17+1j)
>>> import cmath
>>> cmath.sqrt(-1)
1j
>>> pow(-1, .5)
(6.123233995736766e-17+1j)
>>> (-4)**.5
(1.2246467991473532e-16+2j)
>>> 

I also tried with Python 3.1.2 in my 32-bit Ubuntu 10.10 installation and got the same results.

The error seems to be in the floating point (double) representation limit of 16 decimal places.
msg131954 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-03-24 02:51
(-1)**.5 is the same than complex(-1,0)**.5, but it is computed differently than cmath.sqrt(-1).

-1.**0.5 computes:

  vabs = math.hypot(-1, 0)
  len = pow(vabs, 0.5)
  at = math.atan2(0, -1)
  phase = at * 0.5
  return complex(len*math.cos(phase), len*math.sin(phase))

whereas cmath.sqrt(-1) computes:

  ax = math.fabs(-1)
  ay = math.fabs(0)
  ax /= 8.
  s = 2. * math.sqrt(ax + math.hypot(ax, ay/8.))
  d = ay / (2.*s)
  return complex(d, math.copysign(s, 0))

Anyway, math.sqrt() and cmath.sqrt() are designed to be more precise than x**0.5.
msg131966 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2011-03-24 10:59
I don't see a real problem here:  both cmath.sqrt(-1) and (-1)**0.5 are producing good approximations to the correct result, which is about as much as you can hope for in general with floating-point algorithms.

I wouldn't want to start special-casing the complex power algorithm to produce expected results for given bases or exponents;  the code is complex enough as it is.

Patches to improve the general accuracy of complex.__pow__ would be welcome.

Closing as won't fix.
History
Date User Action Args
2022-04-11 14:57:15adminsetgithub: 55867
2011-03-24 10:59:48mark.dickinsonsetstatus: open -> closed
resolution: wont fix
messages: + msg131966
2011-03-24 02:51:20vstinnersetnosy: + mark.dickinson, vstinner
messages: + msg131954
2011-03-24 02:30:52JBernardocreate