23

For a project in one of my classes we have to output numbers up to five decimal places.It is possible that the output will be a complex number and I am unable to figure out how to output a complex number with five decimal places. For floats I know it is just:

print "%0.5f"%variable_name

Is there something similar for complex numbers?

Cœur
  • 37,241
  • 25
  • 195
  • 267
island_hopper
  • 285
  • 1
  • 2
  • 8

6 Answers6

37

You could do it as is shown below using the str.format() method:

>>> n = 3.4+2.3j
>>> n
(3.4+2.3j)
>>> '({0.real:.2f} + {0.imag:.2f}i)'.format(n)
'(3.40 + 2.30i)'
>>> '({c.real:.2f} + {c.imag:.2f}i)'.format(c=n)
'(3.40 + 2.30i)'

To make it handle both positive and negative imaginary portions properly, you would need a (even more) complicated formatting operation:

>>> n = 3.4-2.3j
>>> n
(3.4-2.3j)
>>> '({0:.2f} {1} {2:.2f}i)'.format(n.real, '+-'[n.imag < 0], abs(n.imag))
'(3.40 - 2.30i)'

Update - Easier Way

Although you cannot use f as a presentation type for complex numbers using the string formatting operator %:

n1 = 3.4+2.3j
n2 = 3.4-2.3j

try:
    print('test: %.2f' % n1)
except Exception as exc:
    print('{}: {}'.format(type(exc).__name__, exc))

Output:

TypeError: float argument required, not complex

You can however use it with complex numbers via the str.format() method. This isn't explicitly documented, but is implied by the Format Specification Mini-Language documentation which just says:

'f'  Fixed point. Displays the number as a fixed-point number. The default precision is 6.

. . .so it's easy to overlook. In concrete terms, the following works in both Python 2.7.14 and 3.4.6:

print('n1: {:.2f}'.format(n1))
print('n2: {:.2f}'.format(n2))

Output:

n1: 3.10+4.20j
n2: 3.10-4.20j

This doesn't give you quite the control the code in my original answer does, but it's certainly much more concise (and handles both positive and negative imaginary parts automatically).

Update 2 - f-strings

Formatted string literals (aka f-strings) were added in Python 3.6, which means it could also be done like this in that version or later:

print(f'n1: {n1:.2f}')  # -> n1: 3.40+2.30j
print(f'n2: {n2:.3f}')  # -> n2: 3.400-2.300j

In Python 3.8.0, support for an = specifier was added to f-strings, allowing you to write:

print(f'{n1=:.2f}')  # -> n1=3.40+2.30j
print(f'{n2=:.3f}')  # -> n2=3.400-2.300j
martineau
  • 119,623
  • 25
  • 170
  • 301
  • What if the imaginary part is negative? – Peter Wood Jun 04 '14 at 09:32
  • @Peter: To handle both positive and negative imaginary portions you could use `'({0.real:.2f} {0.imag:+.2f}j)'.format(n)`. – martineau Jun 04 '14 at 10:23
  • That would produce, for example, `(3.40 -2.30j)`. What if you want `(3.40 - 2.30j)`? – Peter Wood Jun 04 '14 at 10:46
  • @Peter: For that you'd need something like `'({0:.2f} {1} {2:.2f}j)'.format(n.real, '+' if n.imag >= 0 else '-', abs(n.imag))`. If you have further questions please post them as such rather than as comments. – martineau Jun 04 '14 at 12:03
  • 1
    Sorry, I was trying to help you correct and improve your answer. With a negative imaginary part it will print, for example, `(3.49 + -2.30j)`. – Peter Wood Jun 04 '14 at 12:11
  • The `abs(n.imag)` should take care of that. – martineau Jun 04 '14 at 12:21
  • Yes, I know the comment is correct. But the answer isn't. Sorry for the confusion. – Peter Wood Jun 04 '14 at 13:24
  • 1
    Thank you for posting this answer. It's frustrating to come to a difficult string formatting thread and have everyone link the docs (which are super unhelpful really), even after admitting that there's no way shown in the docs. I really don't get why python doesn't have something like: '0.2cf' to mean complex float, that would work just like a normal float... – Adam Hughes Jan 16 '15 at 01:33
  • @Adam: I can only speculate but from what I've read it sounds like it might be because Python was originally just a "hobby" programming project of its creator, so handling complex numbers was probably not a high priority -- although by now one would think it might be a little better at doing it. – martineau Jan 16 '15 at 01:51
5

Neither String Formatting Operations - i.e. the modulo (%) operator) - nor the newer str.format() Format String Syntax support complex types. However it is possible to call the __format__ method of all built in numeric types directly. Here is an example:

>>> i = -3 # int
>>> l = -33L # long (only Python 2.X)
>>> f = -10./3 # float
>>> c = - 1./9 - 2.j/9 # complex
>>> [ x.__format__('.3f') for x in (i, l, f, c)]
['-3.000', '-33.000', '-3.333', '-0.111-0.222j']

Note, that this works well with negative imaginary parts too.

martink
  • 51
  • 1
  • 2
4

For questions like this, the Python documentation should be your first stop. Specifically, have a look at the section on string formatting. It lists all the string format codes; there isn't one for complex numbers.

What you can do is format the real and imaginary parts of the number separately, using x.real and x.imag, and print it out in a + bi form.

David Z
  • 128,184
  • 27
  • 255
  • 279
3
>>> n = 3.4 + 2.3j
>>> print '%05f %05fi' % (n.real, n.imag)
3.400000 2.300000i
Facundo Casco
  • 10,065
  • 8
  • 42
  • 63
  • Changed to `'%05f %+05fi' % (n.real, n.imag)` it always shows the imaginary part's sign which looks mathematically nice in both cases: `3.400000 +2.300000i` and `3.400000 -2.300000i`. – flonk Feb 05 '14 at 15:02
1

As of Python 2.6 you can define how objects of your own classes respond to format strings. So, you can define a subclass of complex that can be formatted. Here's an example:

>>> class Complex_formatted(complex):
...     def __format__(self, fmt):
...         cfmt = "({:" + fmt + "}{:+" + fmt + "}j)"
...         return cfmt.format(self.real, self.imag)
... 
>>> z1 = Complex_formatted(.123456789 + 123.456789j)
>>> z2 = Complex_formatted(.123456789 - 123.456789j)
>>> "My complex numbers are {:0.5f} and {:0.5f}.".format(z1, z2)
'My complex numbers are (0.12346+123.45679j) and (0.12346-123.45679j).'
>>> "My complex numbers are {:0.6f} and {:0.6f}.".format(z1, z2)
'My complex numbers are (0.123457+123.456789j) and (0.123457-123.456789j).'

Objects of this class behave exactly like complex numbers except they take more space and operate more slowly; reader beware.

FutureNerd
  • 769
  • 7
  • 9
0

Check this out:

np.set_printoptions(precision=2)  # Rounds up to 2 decimals all float expressions

I've successfully printed my complexfloat's expressions:

# Show poles and zeros
print( "zeros = ", zeros_H , "\n")
print( "poles = ", poles_H )

out before:

zeros =  [-0.8       +0.6j -0.8       -0.6j -0.66666667+0.j ] 

poles =  [-0.81542318+0.60991027j -0.81542318-0.60991027j -0.8358203 +0.j        ]

out after:

zeros =  [-0.8 +0.6j -0.8 -0.6j -0.67+0.j ] 

poles =  [-0.82+0.61j -0.82-0.61j -0.84+0.j  ]