Skip to content

Commit

Permalink
Use floats for signed zeros in the real part of repr(complex)
Browse files Browse the repository at this point in the history
>>> complex(-0.0, 1)  # was (-0+1j)
(-0.0+1j)

This doesn't break complex(str(x)) == x invariant as we
had support for parsing signed 0.0's here before.
  • Loading branch information
skirpichev committed Oct 1, 2024
1 parent 72722e9 commit 737293b
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 8 deletions.
8 changes: 4 additions & 4 deletions Lib/test/test_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,14 +835,14 @@ def test(v, expected, test_fn=self.assertEqual):
test_fn(str(v), expected)

test(complex(0., 1.), "1j")
test(complex(-0., 1.), "(-0+1j)")
test(complex(-0., 1.), "(-0.0+1j)")
test(complex(0., -1.), "-1j")
test(complex(-0., -1.), "(-0-1j)")
test(complex(-0., -1.), "(-0.0-1j)")

test(complex(0., 0.), "0j")
test(complex(0., -0.), "-0j")
test(complex(-0., 0.), "(-0+0j)")
test(complex(-0., -0.), "(-0-0j)")
test(complex(-0., 0.), "(-0.0+0j)")
test(complex(-0., -0.), "(-0.0-0j)")

def test_pos(self):
self.assertEqual(+(1+6j), 1+6j)
Expand Down
4 changes: 2 additions & 2 deletions Objects/complexobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,8 @@ complex_repr(PyComplexObject *v)
} else {
/* Format imaginary part with sign, real part without. Include
parens in the result. */
pre = PyOS_double_to_string(v->cval.real, format_code,
precision, 0, NULL);
pre = PyOS_double_to_string(v->cval.real, format_code, precision,
v->cval.real? 0 : Py_DTSF_ADD_DOT_0, NULL);
if (!pre) {
PyErr_NoMemory();
goto done;
Expand Down
9 changes: 7 additions & 2 deletions Python/formatter_unicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1290,8 +1290,13 @@ format_complex_internal(PyObject *value,
/* Cast "type", because if we're in unicode we need to pass an
8-bit char. This is safe, because we've restricted what "type"
can be. */
re_buf = PyOS_double_to_string(re, (char)type, precision, flags,
&re_float_type);
if (re == 0.0 && copysign(1.0, re) == -1.0)
re_buf = PyOS_double_to_string(re, (char)type, precision,
flags | Py_DTSF_ADD_DOT_0,
&re_float_type);
else
re_buf = PyOS_double_to_string(re, (char)type, precision, flags,
&re_float_type);
if (re_buf == NULL)
goto done;
im_buf = PyOS_double_to_string(im, (char)type, precision, flags,
Expand Down

0 comments on commit 737293b

Please sign in to comment.