# Lecture 5: Complex and Algebraic Numbers¶

We have integer, rational, and irrational numbers. Among the irrational numbers, we distinguish between the algebraic and the transcendental numbers. An algebraic number is a root of a polynomial with integer coefficients. For a transcendental number, there does not exist a polynomial with integer coefficients that has that number as one of its roots. Complex numbers are special type algebraic numbers and merit separate treatment.

Sage knows the symbol `I`

as the imaginary unit.
While we may define `I`

as the square root of negative one, this
definition has its problems, as we then see when we cover algebraic numbers.
A complex number is a special algebraic number and arises from the
polynomial \(x^2 + 1\), which as no real root,
or equivalently, \(x^2 + 1\) does not factor over
the field of real numbers. The outcome of the `factor`

command on a
polynomial in one variable depends on the choice of coefficient field.
We introduce finite fields, multiplication tables, and field extensions.

## Complex Numbers¶

We could define the imaginary unit as the square root of -1 and we see that Sage represents sqrt(-1) with the symbol I.

```
print(sqrt(-1))
print(type(I))
print(I^2)
```

The `I`

has type `sage.symbolic.expression.Expression`

and its square evaluates to \(-1\).

In rectangular coordinates, complex numbers have a real part and an imaginary part.

```
x = 2/3 + 5*I; print(' x =', x, '|x| =', abs(x))
y = complex(2/3,5); print('y =', y, '|x| =', abs(y))
print('x has type', type(x))
print('y has type', type(y))
```

While `x`

is considers as an expression,
the `y`

is the `complex`

type of Python.
As an expression, the real and imaginary part of a complex number
may be any number type, whereas Python’s complex number is a tuple
of two hardware floats.

An alternative to representing a complex number via its real and imaginary part (rectangular coordinates) is the polar representation as its absolute value and an argument. We first must make sure the number belongs to the Complex Double Field, abbreviated by CDF.

```
ax = CDF(x).argument(); rx = abs(x)
print(ax, rx, 'x =', complex(rx*(cos(ax) + I*sin(ax))))
```

and we recognize the rectangular representation of `x`

as we defined `x`

above.

Complex numbers are introduced so every polynomial with real coefficients
of degree d has d roots, counted with multiplicities.
By default, we get complex roots if we solve a polynomial equation.
If we want to see the multiplicities of the roots, we must turn
on the `multiplicities`

flag.

```
var('z')
solve(z^2 + 4 == 0, z)
solve(z^2 - 2*z + 1 == 0, z, multiplicities=True)
```

Defining I as the square root of -1 has its problems, as we will try to illustrate next.

```
a = (-1 + I)^2; b = (1 - I)^2;
```

If we apply the `sqrt()`

function to `a`

and `b`

we would expect to see `-1 + I`

and `1 - I`

respectively.
Instead we get `sqrt(-2*I)`

in both cases. Why?
Because, if we take a square root,
we are solving a quadratic equation.

```
aq = z^2 - a == 0; bq = z^2 - b == 0;
```

The solution is \(\pm \sqrt{-2I}\).
With the option `all`

we get to see all square roots:

```
sqrt(a, all=True)
```

In contrast, we can also prevent evaluation,
after coercing the argument of `sqrt()`

to a symbolic ring,
denoted by SR.

```
sqrt(SR(4), hold=True)
```

## Algebraic Numbers¶

A square root is an algebraic number. The smallest polynomial that has an algebraic number as its root is the minimal polynomial. The command

```
sqrt(2).minpoly()
```

returns \(x^2 - 2\) as the minimal polynomial of \(\sqrt{2}\).

The outcome of the factoring of a polynomial depends on the number field.

```
print(factor(z^2 - 1))
print(factor(z^2 - 2))
```

The first command will print `(z + 1)*(z - 1)`

whereas the second
polynomial does factor and we get `z^2 - 2`

returned.
If a polynomial does not factor over a specific number field
(the default number field is the field of rational numbers),
then we say that the polynomial is *irreducible over that specific
number field*.

We can define a number field where `c`

is the square root of 2,
we can compute modulo the minimal polynomial of sqrt(2),
that is `c^2 - 2 = 0`

.
We use `c^2 = 2`

to simplify expressions in `c`

.

```
K.<c> = NumberField(x^2 - 2); print K
print(c^2 - 2)
print(c^3)
```

The defining polynomial of the number field `K`

is `x^2 - 2`

.
In this number field, the expression `c^2 - c`

evaluates to zero
and `c^3`

simplifies to `2*c`

.
If we now consider a polynomial ring over the number field K,
then the polynomial x^2 - 2 will factor.

```
R.<x> = PolynomialRing(K)
p = x^2 - 2
factor(p)
```

On return we see `(x - c) * (x + c)`

.

In coding and cryptography we often work with finite fields.

```
k = GF(8,'c'); print(k)
e = [a for a in k]; print(e)
```

The `GF`

is an abbreviation for Galois Field.
This makes `k`

a field of size \(2^3\) with elements

```
[0, c, c^2, c + 1, c^2 + c, c^2 + c + 1, c^2 + 1, 1]
```

In a field every element has a multiplicative inverse. We can see this in table of multiplications.

```
for x in e: [x*y for y in e]
```

The multiplication table is

```
[0, 0, 0, 0, 0, 0, 0, 0]
[0, c^2, c + 1, c^2 + c, c^2 + c + 1, c^2 + 1, 1, c]
[0, c + 1, c^2 + c, c^2 + c + 1, c^2 + 1, 1, c, c^2]
[0, c^2 + c, c^2 + c + 1, c^2 + 1, 1, c, c^2, c + 1]
[0, c^2 + c + 1, c^2 + 1, 1, c, c^2, c + 1, c^2 + c]
[0, c^2 + 1, 1, c, c^2, c + 1, c^2 + c, c^2 + c + 1]
[0, 1, c, c^2, c + 1, c^2 + c, c^2 + c + 1, c^2 + 1]
[0, c, c^2, c + 1, c^2 + c, c^2 + c + 1, c^2 + 1, 1]
```

Observe that, except for the first row, there is 1 in every row. Except for the first column, there is 1 in every column. To verify, let us look at the 1 in the second row.

```
print e[1], '* (', e[-2], ') =', e[1]*e[-2]
```

The output is `c * ( c^2 + 1 ) = 1`

.

We can factor over finite fields. We make a polynomial ring with coefficients in the finite field we just constructed:

```
R.<x> = PolynomialRing(k)
p = x^3 + x + 1
factor(p)
```

which leads to `(x + c) * (x + c^2) * (x + c^2 + c)`

.
Note that over the default field, the polynomial is irreducible.

```
q = z^3 + z + 1; factor(q)
```

To verify that the polynomial \(p = x^4 + 3 x + 4\) does not factor over the finite field of five elements, we do

```
R.<x> = PolynomialRing(GF(5))
p = x^4 + 3*x + 4; print factor(p)
```

We can then extend the field of five elements with a root of \(p\) as follows

```
F.<a> = GF(5).extension(p)
e = [n for n in F]; print e
```

Because the degree of \(p\) is four, every element in the
field extension `F`

can be expressed as a polynomial of degree three
or less, because every fourth power of \(a\) simplifies
via \(a^4 = 2 a + 1\). We have five choices for every
coefficient of a degree three polynomials and since we can make
those choices independently, we have a field with \(5^4\) elements.
Over this field extension, we have a factorization.

```
R.<y> = PolynomialRing(F)
q = y^4 + 3*y + 4; print(factor(q))
```

## Assignments¶

The complex number \(z\) in polar representation is given by the radius (absolute value) \(r = 3\) and angle (argument) \(\theta = \pi/3\). Use Sage to find the exact (no floating-point) value of \(z\) in the form \(a + b I\).

Execute

`solve(x^3 - 5 == 0, x)`

and show that all solutions of \(x^3 - 5 = 0\) are of the form \(\sqrt[3]{5} e^{I \theta}\), with \(\theta\) being either 0 or \(\pm \frac{2}{3} \pi\).Take the complex number \(z = 1 + I\) and let Sage compute \(\sqrt{1/z}\) and \(1/\sqrt{z}\). Are the results symbolically the same? Are the results numerically the same? Give reasons for your answers, illustrated with the appropriate Sage instructions.

Use Sage to show that the polynomial \(p = x^4 + 3 x + 4\) is irreducible over the finite field with 5 elements. Declare \(z\) to be a root of \(p\) and express \(z^{13}\) as a polynomial in \(z\) of degree 4 (or less).

Compute all irreducible polynomials of degree 2 over a field with 3 elements.