11

How can I round up a complex number (e.g. 1.9999999999999998-2j) as 2-2j?

When I tried using

print(round(x,2))

it showed

Traceback (most recent call last):
  File "C:\Python34\FFT.py", line 22, in <module>
    print(round(x,2))
TypeError: type complex doesn't define __round__ method
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
prav
  • 165
  • 1
  • 2
  • 8

5 Answers5

10

Round real part and imaginary part separately and combine them:

>>> num = 1.9999999999999998-2j
>>> round(num.real, 2) + round(num.imag, 2) * 1j
(2-2j)
falsetru
  • 357,413
  • 63
  • 732
  • 636
10

If all you want to do is represent the value rounded as shown, rather than modify the value itself, the following works:

>>> x=1.9999999999999998-2j
>>> print("{:g}".format(x))
2-2j

See: Format Specification Mini-Language.

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • To round up numbers that aren't cause by floating point precision i.e. `2.9+1j` you can use a small precision format like `f"{2.9+1j:.0g}"`. Beware this hack does not work for small numbers: `f"{.9+1j:.0g}"` = `'0.9+1j'`. – Carl Walsh Mar 26 '21 at 22:36
  • You can force rounding small numbers with format `f` instead of `g`, like `f"{.9+1j:.0f}"` gives `'1+1j'` (I don't know why I didn't find that a year ago) – Carl Walsh May 31 '22 at 19:40
3

Id say the best way to do it is as such

x = (1.542334+32.5322j)
x = complex(round(x.real),round(x.imag))

if you don't want to repeat that every time you want to do it, you could put it in a function.

def round_complex(x):
    return complex(round(x.real),round(x.imag))

Additional optional arguments can then be added to this, so if you only want to round one part for example, or if you only want to round to a certain number of decimal places on either the real or complex part

def round_complex(x, PlacesReal = 0, PlacesImag = 0, RoundImag = True, RoundReal = True):
     if RoundImag and not RoundReal:
         return complex(x.real,round(x.imag,PlacesImag))

     elif RoundReal and not RoundImag:
         return complex(round(x.real,PlacesReal),x.imag)

     else: #it would be a waste of space to make it do nothing if you set both to false, so it instead does what it would if both were true
         return complex(round(x.real,PlacesReal),round(x.imag,PlacesImag))

as the variables are auto set to true or 0, you don't need to input them unless you specifically want too. But they are handy to have

Evelyn
  • 85
  • 8
1

Well, perhaps you can write your own _complex for local use? Here's an example:

class _complex(complex):
    def __round__(self, n=None):
        try:
            assert isinstance(n, int)
        except AssertionError:
            raise ValueError(f"n must be an integer: {type(n)}")
        if n is not None:
            return complex(round(self.real, n), round(self.imag, n))
        return self

And you use it like:

c = _complex(1, 2)
print(round(c, 4))

Very rough... may require some cleanup. I'm surprised this is not in the Python standard library.

polarise
  • 2,303
  • 1
  • 19
  • 28
0

You could round the real part and imaginary part separately rather than combined. Like:

x=complex(1.9999999999999998,-2)
rounded_x=complex(round(x.real,2),round(x.imag,2))

Then you could print the rounded_x variable as a string(to avoid the brackets when printing). Hope this short answer helps the readers including the questioner.