В этой статье я объясню, что такое комплексные числа, и как они могут пригодиться в решении геометрических задач по программированию.
Давайте назовем комплексным числом пару вещественных чисел a и b, и обозначим его как (a, b). Число a будем называть вещественной частью, а число b — мнимой.
Определим операцию сложения для двух комплексных чисел:
(a, b) + (c, d) = (a + c, b + d).
Заметим, что сложение в комплексных числах обладает теми же свойствами, что и в вещественных.
Введем операцию умножения:
(a, b) * (c, d) = (a*c — b*d, a*d + b*c)
Не трудно убедиться, что умножение в комплексных числах тоже обладает теми же свойствами, что и в вещественных.
Будем считать, что если мнимая часть в комплексном числе равна нулю, то само число равно его вещественной части. Действительно, если сложить (a, 0) и (b, 0), получится как раз (a + b, 0), а если перемножить (a, 0) и (b, 0), получится (a*b, 0).
Обозначим число (0, 1) за i. Заметим, что i^2 = (0, 1) * (0, 1) = (-1, 0). Следовательно i равно корню из -1.
Теперь давайте представлять комплексное число не просто как пару чисел, а как сумму его вещественной части и мнимой части, умноженной на i.
z = a + b*i.
Пусть, z = a + b*i, u = c + d*i.
z + u = (a + b*i) + (c + d*i) = (a + c) + (b + d)*i, что как раз равно числу (a + c, b + d);
z * u = (a + b*i) * (c + d*i) = a*c + (a*d + b*c)*i + b*d*(i^2) = (a*c — b*d) + (a*d + b*c)*i, что равно числу (a*c — b*d, a*d + b*c).
Сопряжённым к комплексному числу a + b*i назовем число a — b*i, обозначим conj(z). Модулем числа a + b*i назовем sqrt(a^2 + b^2). Не трудно убедиться, что conj(z) + conj(w) = conj(z + w), conj(z) * conj(w) = conj(z * w) и |z| * |w| = |z * w|.
Заметим, что z * conj(z) = (a + b*i) * (a — b*i) = a*a + b*b = |z|^2. Мы можем делить комплексное число z на вещественное (a, 0) — достаточно лишь умножить z на (1/a, 0). Следовательно, z * (conj(z) / (|z|^2)) = 1. Значит z^(-1) = conj(z) / (|z| ^ 2). Покажем также, что такое число единственно. Пусть (a + b*i) * (x + y*i) = 1. Получаем систему уравнений
a*x — b*y = 1
a*y + b*x = 0
Система из двух уравнений с двумя неизвестными имеет не более одного решения. Значит, мы теперь можем делить комплексное число z на комплексное w, достаточно умножить z на w^(-1).
Пусть, z != 0. Рассмотрим число z / |z|. У него модуль равен 1, значит a^2 + b^2 = 1, а значит существует такой угол phi, что a = cos(phi), b = sin(phi). Назовем такой угол аргументом комплексного числа, обозначим за arg(z).
За e^(i*phi) пока что просто обозначим число cos(phi) + sin(phi)*i. Тогда каждое комплексное число z представимо в виде |z| * e^(i*arg(z)).
Докажем, что e^(i*phi) — это действительно phi-тая степень какого-то числа. Очевидно, что e^(i*0) = 1. Нам осталось доказать, что при умножении аргументы двух комплексных чисел складываются. Допустим, первое число равно a * e^(i*alpha), а второе — b * e^(i*beta). Их произведение равно a * b * (cos(alpha)*cos(beta) — sin(alpha)*sin(beta) + (sin(alpha)*cos(beta) + cos(alpha)*sin(beta))*i) = a * b * (cos(alpha + beta) + sin(alpha + beta)*i). Значит, при перемножении модули перемножаются, а аргументы складываются.
Ближе к делу: определим, что такое комплексная плоскость. Каждой точке на плоскости мы сопоставим комплексное число, а именно точке с координатами (x, y) мы сопоставим число x + y*i.

Пусть точке Z соответствует число z. Пусть, O — начало координат. Тогда длина отрезка OZ будет равна |z|, а направленный угол наклона OZ относительно Ox будет равен arg(z).
Сначала рассмотрим какие преобразования плоскости легко реализовать в комплексных числах. То есть, допустим, у нас есть задача: задано преобразование плоскости, найти куда переходит точка A.
1. Параллельный перенос на вектор a. Пусть w — комплексное число соответствующее вектору a (то есть, точке полученной при отложении a от начала координат). Тогда, очевидно, число z перейдет в z + w.
2. Гомотетия с центром в точке W и коэффициентом k. Сначала рассмотрим более простой вариант: гомотетия с коэффициентом k и с центром в точке 0. В таком случае z просто переходит в z * k. Вернемся к исходной задаче. Давайте сначала переведем параллельным переносом точку W в 0, затем умножим все на k, а затем сделаем параллельный перенос обратно, то есть на противоположный вектор. Итак, z переходит в (z — w) * k + w.
3. Поворот с центром в точке W на угол alpha. Давайте опять сначала рассмотрим поворот на угол alpha с центром в точке 0. Тогда z переходит в z * e^(i*alpha). Тогда в общем случае z переходит в (z — w) * e^(i*alpha) + w.
4. Поворотная гомотетия с центром в точке W, с коэффициентом k на угол alpha. Воспользуемся тем, что мы уже знаем и сразу выведем формулу: z перейдет в (z — w) * k * e^(i*alpha) + w.
5. Осевая симметрия относительно прямой l. Опять же рассмотрим сначала частный случай: осевая симметрия относительно прямой Ox. В таком случае z переходит в conj(z). Значит в общем случае, если l пересекалась с Ox в точке W и направленный угол между Ox и l равен phi, то надо сделать поворот на угол -phi в точке W, затем отразить, а затем сделать поворот обратно на угол phi. Значит, z перейдет в (conj( (z — w) * e^(-i*phi) + w ) — w) * e^(i*phi) + w. Если же Ox и l параллельны и W — любая точка на l, то z перейдет в conj(z — w) + w.
Двойным отношением четырех чисел a, b, c, d назовем отношение ((a — c)/(b — c)) / ((a — d)/(b — d)).
Сначала рассмотрим простую задачу: узнать, лежат ли три точки на одной прямой. Пусть нам даны точки A, B, C. Тогда они лежат на одной прямой тогда и только тогда, когда векторы AB и BC коллинеарны. Но вектор AB = XB — XA для любого X. Значит, комплексное число, соответствующее вектору AB — это b — a, а вектору BC — число c — b. Значит, они лежат на одной прямой тогда и только тогда, когда у чисел b — a и c — b одинаковые аргументы (по модулю pi), то есть у числа (b — a) / (c — b) аргумент равен 0 по модулю pi, то есть оно вещественно.
Теперь, докажем, что четыре точки лежат на одной окружности или прямой тогда и только тогда, когда их двойное отношение вещественно.
Теперь рассмотрим следующую задачу: требуется узнать находятся ли 4 точки на одной окружности или прямой. В комплексных числах это можно узнать, вычислив всего одно значение.

Заметим, что на картинке CA/CB и DA/DB — вещественные, следовательно двойное отношение вещественно тогда и только тогда, когда вещественно e^(i*alpha) / e^(i*beta) = e^(i*(alpha — beta)), то есть тогда и только тогда, когда alpha = beta, что равносильно тому, что эти четыре точки лежат на одной окружности или прямой.
Основы
Давайте назовем комплексным числом пару вещественных чисел a и b, и обозначим его как (a, b). Число a будем называть вещественной частью, а число b — мнимой.
Определим операцию сложения для двух комплексных чисел:
(a, b) + (c, d) = (a + c, b + d).
Заметим, что сложение в комплексных числах обладает теми же свойствами, что и в вещественных.
Введем операцию умножения:
(a, b) * (c, d) = (a*c — b*d, a*d + b*c)
Не трудно убедиться, что умножение в комплексных числах тоже обладает теми же свойствами, что и в вещественных.
Будем считать, что если мнимая часть в комплексном числе равна нулю, то само число равно его вещественной части. Действительно, если сложить (a, 0) и (b, 0), получится как раз (a + b, 0), а если перемножить (a, 0) и (b, 0), получится (a*b, 0).
Обозначим число (0, 1) за i. Заметим, что i^2 = (0, 1) * (0, 1) = (-1, 0). Следовательно i равно корню из -1.
Теперь давайте представлять комплексное число не просто как пару чисел, а как сумму его вещественной части и мнимой части, умноженной на i.
z = a + b*i.
Пусть, z = a + b*i, u = c + d*i.
z + u = (a + b*i) + (c + d*i) = (a + c) + (b + d)*i, что как раз равно числу (a + c, b + d);
z * u = (a + b*i) * (c + d*i) = a*c + (a*d + b*c)*i + b*d*(i^2) = (a*c — b*d) + (a*d + b*c)*i, что равно числу (a*c — b*d, a*d + b*c).
Сопряжённым к комплексному числу a + b*i назовем число a — b*i, обозначим conj(z). Модулем числа a + b*i назовем sqrt(a^2 + b^2). Не трудно убедиться, что conj(z) + conj(w) = conj(z + w), conj(z) * conj(w) = conj(z * w) и |z| * |w| = |z * w|.
Заметим, что z * conj(z) = (a + b*i) * (a — b*i) = a*a + b*b = |z|^2. Мы можем делить комплексное число z на вещественное (a, 0) — достаточно лишь умножить z на (1/a, 0). Следовательно, z * (conj(z) / (|z|^2)) = 1. Значит z^(-1) = conj(z) / (|z| ^ 2). Покажем также, что такое число единственно. Пусть (a + b*i) * (x + y*i) = 1. Получаем систему уравнений
a*x — b*y = 1
a*y + b*x = 0
Система из двух уравнений с двумя неизвестными имеет не более одного решения. Значит, мы теперь можем делить комплексное число z на комплексное w, достаточно умножить z на w^(-1).
Пусть, z != 0. Рассмотрим число z / |z|. У него модуль равен 1, значит a^2 + b^2 = 1, а значит существует такой угол phi, что a = cos(phi), b = sin(phi). Назовем такой угол аргументом комплексного числа, обозначим за arg(z).
За e^(i*phi) пока что просто обозначим число cos(phi) + sin(phi)*i. Тогда каждое комплексное число z представимо в виде |z| * e^(i*arg(z)).
Докажем, что e^(i*phi) — это действительно phi-тая степень какого-то числа. Очевидно, что e^(i*0) = 1. Нам осталось доказать, что при умножении аргументы двух комплексных чисел складываются. Допустим, первое число равно a * e^(i*alpha), а второе — b * e^(i*beta). Их произведение равно a * b * (cos(alpha)*cos(beta) — sin(alpha)*sin(beta) + (sin(alpha)*cos(beta) + cos(alpha)*sin(beta))*i) = a * b * (cos(alpha + beta) + sin(alpha + beta)*i). Значит, при перемножении модули перемножаются, а аргументы складываются.
Ближе к делу: определим, что такое комплексная плоскость. Каждой точке на плоскости мы сопоставим комплексное число, а именно точке с координатами (x, y) мы сопоставим число x + y*i.

Пусть точке Z соответствует число z. Пусть, O — начало координат. Тогда длина отрезка OZ будет равна |z|, а направленный угол наклона OZ относительно Ox будет равен arg(z).
Преобразования плоскости в комплексных
Сначала рассмотрим какие преобразования плоскости легко реализовать в комплексных числах. То есть, допустим, у нас есть задача: задано преобразование плоскости, найти куда переходит точка A.
1. Параллельный перенос на вектор a. Пусть w — комплексное число соответствующее вектору a (то есть, точке полученной при отложении a от начала координат). Тогда, очевидно, число z перейдет в z + w.
2. Гомотетия с центром в точке W и коэффициентом k. Сначала рассмотрим более простой вариант: гомотетия с коэффициентом k и с центром в точке 0. В таком случае z просто переходит в z * k. Вернемся к исходной задаче. Давайте сначала переведем параллельным переносом точку W в 0, затем умножим все на k, а затем сделаем параллельный перенос обратно, то есть на противоположный вектор. Итак, z переходит в (z — w) * k + w.
3. Поворот с центром в точке W на угол alpha. Давайте опять сначала рассмотрим поворот на угол alpha с центром в точке 0. Тогда z переходит в z * e^(i*alpha). Тогда в общем случае z переходит в (z — w) * e^(i*alpha) + w.
4. Поворотная гомотетия с центром в точке W, с коэффициентом k на угол alpha. Воспользуемся тем, что мы уже знаем и сразу выведем формулу: z перейдет в (z — w) * k * e^(i*alpha) + w.
5. Осевая симметрия относительно прямой l. Опять же рассмотрим сначала частный случай: осевая симметрия относительно прямой Ox. В таком случае z переходит в conj(z). Значит в общем случае, если l пересекалась с Ox в точке W и направленный угол между Ox и l равен phi, то надо сделать поворот на угол -phi в точке W, затем отразить, а затем сделать поворот обратно на угол phi. Значит, z перейдет в (conj( (z — w) * e^(-i*phi) + w ) — w) * e^(i*phi) + w. Если же Ox и l параллельны и W — любая точка на l, то z перейдет в conj(z — w) + w.
Двойное отношение
Двойным отношением четырех чисел a, b, c, d назовем отношение ((a — c)/(b — c)) / ((a — d)/(b — d)).
Сначала рассмотрим простую задачу: узнать, лежат ли три точки на одной прямой. Пусть нам даны точки A, B, C. Тогда они лежат на одной прямой тогда и только тогда, когда векторы AB и BC коллинеарны. Но вектор AB = XB — XA для любого X. Значит, комплексное число, соответствующее вектору AB — это b — a, а вектору BC — число c — b. Значит, они лежат на одной прямой тогда и только тогда, когда у чисел b — a и c — b одинаковые аргументы (по модулю pi), то есть у числа (b — a) / (c — b) аргумент равен 0 по модулю pi, то есть оно вещественно.
Теперь, докажем, что четыре точки лежат на одной окружности или прямой тогда и только тогда, когда их двойное отношение вещественно.
Теперь рассмотрим следующую задачу: требуется узнать находятся ли 4 точки на одной окружности или прямой. В комплексных числах это можно узнать, вычислив всего одно значение.

Заметим, что на картинке CA/CB и DA/DB — вещественные, следовательно двойное отношение вещественно тогда и только тогда, когда вещественно e^(i*alpha) / e^(i*beta) = e^(i*(alpha — beta)), то есть тогда и только тогда, когда alpha = beta, что равносильно тому, что эти четыре точки лежат на одной окружности или прямой.