Скалярное и псевдоскалярное произведение
Скалярное произведение отвечает на вопрос «насколько сонаправлены?», а псевдоскаляр — «по какую сторону и насколько закручено?».
Скалярное произведение $\vec a \cdot \vec b$ — число, равное произведению длин на косинус угла между векторами.
Скалярное произведение
Скалярное произведение определяется покомпонентно и связано с углом:
$$\vec a \cdot \vec b = a_x b_x + a_y b_y = |\vec a|\,|\vec b|\cos\theta.$$
Из второй формы видно его суть: знак скалярного произведения говорит об угле. Если $\vec a\cdot\vec b \gt 0$ — угол острый (векторы «смотрят в одну сторону»); если $\lt 0$ — тупой (в разные); если $= 0$ — векторы перпендикулярны. Это мгновенный тест: «враг впереди или за спиной?» — берём вектор «куда смотрю» и вектор «на врага», их скалярное произведение положительно, если враг в поле зрения. А деля на длины, получаем косинус угла напрямую.
Псевдоскалярное произведение (2D-крест)
В 2D векторное произведение вырождается в одно число — псевдоскаляр:
$$\vec a \times \vec b = a_x b_y - a_y b_x = |\vec a|\,|\vec b|\sin\theta.$$
Оно несёт другую информацию. Его модуль — площадь параллелограмма на векторах (а половина — площадь треугольника). Его знак говорит о направлении поворота от $\vec a$ к $\vec b$: положительный — против часовой стрелки, отрицательный — по часовой. Это решает классическую задачу «с какой стороны от прямой лежит точка», без которой не построить ни проверку выпуклости, ни обход полигона, ни определение, в какую сторону объехать препятствие.
import math
def dot(a, b): return a[0]*b[0] + a[1]*b[1]
def cross(a, b): return a[0]*b[1] - a[1]*b[0]
def length(a): return math.hypot(a[0], a[1])
a = (3, 4)
b = (1, 2)
d = dot(a, b)
c = cross(a, b)
cos_t = d / (length(a)*length(b))
print("dot a·b =", d)
print("cross a×b =", c)
print("cos угла =", round(cos_t, 4))
print("угол, ° =", round(math.degrees(math.acos(cos_t)), 2))
print("площадь треугольника =", abs(c)/2)
Вывод:
dot a·b = 11 cross a×b = 2 cos угла = 0.9839 угол, ° = 10.3 площадь треугольника = 1.0
Скалярное произведение $11 \gt 0$ — векторы образуют острый угол ($10.3°$, они почти сонаправлены). Псевдоскаляр $2 \gt 0$ — поворот от $\vec a$ к $\vec b$ идёт против часовой стрелки, а площадь треугольника на этих векторах равна $1$. Два числа — и мы знаем про взаимное расположение векторов почти всё.
Проекция одного вектора на другой
Скалярное произведение даёт проекцию. Длина проекции $\vec a$ на направление $\hat b$ равна $\vec a\cdot\hat b$. Это нужно, например, чтобы разложить скорость на «вдоль поверхности» и «по нормали» при скольжении — основа реакции на наклонные стены и трамплины.
Как работает под капотом
Обе операции — всего пара умножений и сложение, без тригонометрии и корней, поэтому они невероятно дёшевы и используются в движках буквально на каждом шаге. Важный приём: чтобы узнать знак косинуса (острый угол или тупой), не нужен acos — достаточно знака скалярного произведения. Аналогично сторону поворота определяет знак псевдоскаляра. Избегание тригонометрии там, где нужен лишь знак, — стандартная оптимизация геометрического кода.
Частые ошибки
- Путать скаляр и псевдоскаляр. $\vec a\cdot\vec b$ — про угол/проекцию, $\vec a\times\vec b$ — про площадь/сторону. Это разные числа с разным смыслом.
- Звать
acosради знака угла. Знак скалярного произведения уже отвечает «острый или тупой», корни и арккосинусы лишние. - Забывать про знак псевдоскаляра. Его модуль — площадь, но именно знак различает «слева» и «справа».
Итог
- $\vec a\cdot\vec b = |\vec a||\vec b|\cos\theta$: знак различает острый/тупой угол, даёт проекцию.
- $\vec a\times\vec b = |\vec a||\vec b|\sin\theta$: модуль — площадь, знак — сторона поворота.
- Обе операции дёшевы (без корней и тригонометрии) и применяются на каждом шаге.
- Для определения стороны/знака угла не нужен
acos— хватает знаков произведений.