EduBrick

Скалярное произведение

Одно число, по знаку которого видно, смотрят векторы в одну сторону или в разные. Проекция, перпендикулярность и угол.

3 мин

Скалярное произведение двух векторов — число:

(a,b)=abcosα=axbx+ayby(\vec{a}, \vec{b}) = |\vec{a}| \cdot |\vec{b}| \cdot \cos\alpha = a_x b_x + a_y b_y

Два выражения равны — это несложное упражнение на раскрытие скобок. Пользоваться будем вторым: оно считается по координатам, без всякой тригонометрии.

Скалярное произведение симметрично: (a,b)=(b,a)(\vec{a}, \vec{b}) = (\vec{b}, \vec{a}). Косинусу безразлично направление угла, потому что cos(α)=cosα\cos(-\alpha) = \cos\alpha.

Геометрический смысл

Величина bcosα|\vec{b}| \cos\alpha — длина проекции b\vec{b} на направление a\vec{a} (со знаком). Значит,

(a,b)=a(проекция b на a)(\vec{a}, \vec{b}) = |\vec{a}| \cdot (\text{проекция } \vec{b} \text{ на } \vec{a})

Отсюда — вся польза.

Знак

знак (a,b)(\vec{a}, \vec{b}) угол смысл
положительный меньше 90°90° смотрят «в одну сторону»
ноль ровно 90°90° перпендикулярны
отрицательный больше 90°90° смотрят «в разные стороны»

Это первое из двух главных применений: проверка перпендикулярности и проверка «вперёд или назад».

if (a * b == 0) { /* перпендикулярны */ }
if (a * b > 0)  { /* смотрят в одну сторону */ }

шаблоне скалярное произведение обычно вешают на operator*.)

Косинус и угол

Из определения сразу получается косинус:

cosα=axbx+aybyab\cos\alpha = \frac{a_x b_x + a_y b_y}{|\vec{a}| \cdot |\vec{b}|}

Соблазн взять acos от этого и получить угол. Так делать можно, но с оговоркой: acos возвращает значение от 00 до π\pi, то есть теряет знак угла. Развёрнут ли b\vec{b} относительно a\vec{a} влево или вправо, по косинусу не узнать.

Правильный способ — функция atan2, которая берёт оба произведения сразу:

long double angle = atan2(a % b, a * b);   // векторное, затем скалярное

Она возвращает угол от π-\pi до π\pi, со знаком, и не требует ручного разбора случаев. Порядок аргументов запомнить легко: сначала то, что отвечает за синус (векторное), потом за косинус (скалярное).

Есть и вторая причина не считать угол без нужды: acos теряет точность у краёв диапазона, а из-за погрешности аргумент вообще может оказаться чуть больше единицы, и функция вернёт NaN. Если задача не просит угол явно — не считайте его.

Проекция точки

Проекция вектора v\vec{v} на направление u\vec{u}:

proj=(u,v)u2u\text{proj} = \frac{(\vec{u}, \vec{v})}{|\vec{u}|^2} \cdot \vec{u}

Знаменатель — квадрат длины, а не длина: одно деление вместо корня и нормировки.

Этим считается проекция точки на прямую и, через неё, симметричная точка.

Целые числа

Если координаты целые, скалярное произведение целое — никаких потерь точности. Считайте его в long long: при координатах до 10910^9 произведение доходит до 101810^{18}, и int переполнится молча.

Это одна из самых частых ошибок в геометрии: шаблон, написанный когда-то с int, годами работает и однажды даёт неверный ответ на большом тесте.

Что оно не умеет

Скалярное произведение не различает «слева» и «справа». Векторы b\vec{b} и его отражение относительно a\vec{a} дают одинаковое скалярное произведение — угол-то по модулю тот же.

Для стороны нужно векторное произведение. Вместе они полностью определяют взаимное расположение двух векторов.