Working with Complex Numbers in C++
The complex header defines the usual mathematical functions for complex numbers, including a square root function and the pow() function for exponentiation.
Why Complex Numbers Need Library Functions
A complex number has two parts, a real part and an imaginary part, and ordinary arithmetic on it follows its own rules. Addition and multiplication are often not enough. A program may also need to take a square root of a complex value or raise it to a power. The C++ standard library supplies these operations for complex numbers, so a programmer does not have to write the underlying mathematics by hand each time.
What do you think happens?
Before reading on: if you square the complex number $z = 1 + 2i$ by multiplying it by itself, what do you expect the real part of the result to be?
Reveal answer
The real part is -3, and the full result is -3 + 4i.
The real part does not stay at 1 and is not a sum of squares. The cross term 2i times 2i contributes 4i^{2} = -4, and that negative value is what changes the real part.
Two Functions for Complex Values
The complex header defines the usual mathematical functions for complex numbers. Two of them are central here. The first is a square root function. The source material writes its name as sqr_t(), but in standard C++ it is called sqrt. The second is the pow() function, which raises a complex base to a power. Both belong to the same set of functions, and both take a complex value as input and return a complex value as output.
pow(z, n) raises the complex base z to the power n. When the power is 2, the result equals multiplying the base by itself. sqrt(z) returns a complex value that, when squared, gives the number you started with.
Tracing Exponentiation as Repeated Multiplication
Exponentiation of a complex number is repeated multiplication. For a whole-number exponent n, the value $z^{n}$ means $z$ multiplied by itself n times. The state of the calculation changes at every step, so it helps to watch the value build up from the starting point to the final answer.
Squaring 1 + 2i by hand
Compute $z^{2}$ when $z = 1 + 2i$, using the rule that squaring means multiplying the value by itself.
- 1Write the product
$z^{2} = (1 + 2i)(1 + 2i)$. This is the repeated multiplication from the definition.
- 2Expand every term
Multiply each term in the first factor by each term in the second: $1 \cdot 1 + 1 \cdot 2i + 2i \cdot 1 + 2i \cdot 2i$.
- 3Collect the simple terms
The first three terms give $1 + 2i + 2i = 1 + 4i$.
- 4Handle the imaginary unit
The last term is $2i \cdot 2i = 4i^{2}$. Because $i^{2} = -1$, this becomes $-4$.
- 5Combine the parts
Adding $-4$ to the real part gives $(1 - 4) + 4i = -3 + 4i$.
$z^{2} = -3 + 4i$. The real part is -3, not 1 and not 5.
Why the Real and Imaginary Parts Mix
A tempting shortcut is to square the real part and the imaginary part separately. That shortcut is wrong for complex numbers. The source explains that exponentiation of a complex number produces real and imaginary parts that both depend on the cross terms. In the example above, the two products $1 \cdot 2i$ and $2i \cdot 1$ contribute to the imaginary part, while $2i \cdot 2i$ contributes to the real part through $i^{2} = -1$.
Square Roots as the Reverse of Squaring
The square root function is easiest to understand through a simple case. Since $i^{2} = -1$, the number $i$ is a square root of $-1$. Taking the square root of a complex number asks the reverse question: which complex value, when squared, gives the number you started with. This matters because the square root of a negative real number is not a real number, which is exactly why a complex version of the function is needed.
Calling pow and sqrt in a Program
The example below uses the complex header and calls both functions on the same value. The point is to see that each call has a different purpose. The pow call squares the value, and the sqrt call asks for a value whose square is the original.
- #include <complex> brings in the complex functions
- std::
pow(z, 2)raises z to the power 2, which equals z multiplied by itself - std::sqrt(z) returns a value whose square is z, not a power of z
The value printed for squared should match the hand calculation of $-3 + 4i$, and the value printed for root can be checked by squaring it and confirming the result is $1 + 2i$. Checking a library result this way is the same habit the source recommends: know what answer the function should give before you rely on it.
Mistakes When Choosing Between pow and sqrt
Common mistake Using pow when you want a square root
What it looks likeWriting pow(z, 2) when the goal is to find a value w with w squared equal to z.
Why it failspow(z, 2)squares z. It answers the forward question, not the reverse one.Do this insteadUse sqrt(z) when you need a value whose square is z.
Common mistake Using sqrt when you want to square a value
What it looks likeWriting sqrt(z) to compute z times z.Why it failssqrt returns a root of z, which is a different number from z squared.
Do this insteadUse pow(z, 2), or multiply z by itself directly, to square a value.
Common mistake Squaring the real and imaginary parts separately
What it looks likeTreating (1 + 2i) squared as 1 squared plus 2 squared, which gives 5.
Why it failsThe cross terms and the rule $i^{2} = -1$ change both parts of the result.
Do this insteadExpand the product fully, giving -3 + 4i for z = 1 + 2i.
Common mistake Trusting a library result without checking it against a hand calculation
Checking Results by Hand
Let $z = 2 + i$. Expand $z^{2}$ by multiplying the value by itself, simplify using $i^{2} = -1$, and state both the real and imaginary parts. Then decide which C++ call, pow or sqrt, you would use if the goal were to find a value that squares to $z$.
Hints
- Write $(2 + i)(2 + i)$ and expand all four products.
- The only term that needs special care is $i \cdot i$.
- The square root question is a different question from the squaring question.
Key Takeaways
- The C++ complex header provides the usual mathematical functions for complex numbers, including a square root function (sqrt in standard C++) and
pow()for exponentiation. - Exponentiation of a complex number is repeated multiplication, and with a power of 2 the result equals multiplying the base by itself.
- Because $i^{2} = -1$, the real and imaginary parts of a squared complex number both depend on the cross terms, so squaring the parts separately gives wrong results.
- sqrt answers the reverse question of squaring, while pow answers the forward question, so the two functions should not be confused.
- Expand a product by hand to check the output of a library function before relying on it.