Большие координаты: где кончается 64 бита
Сколько разрядов нужно на векторное произведение и площадь при координатах до 10^9, и что делать, когда их не хватает.
2 мин
Все геометрические предикаты - это произведения координат. Значит первый вопрос при координатах до : помещается ли результат в целочисленный тип.
Три величины и три оценки
| величина | при координатах до | при |
|---|---|---|
| произведение координат | ||
| косое произведение разностей | ||
| удвоенная площадь многоугольника |
Граница знакового 64-битного типа - . То есть при всё три величины умещаются, но запас составляет всего 13%.
Замер на предельных многоугольниках подтверждает оценку: у квадрата во весь диапазон удвоенная площадь равна ровно - это 86,7% от границы long long. У круга радиуса - , то есть 68%.
Что переполняется наверняка
int - на первом же слагаемом: против границы . Причём молча: программа не падает, а печатает правдоподобное число.
Отсюда практическое правило: в геометрии int не используется вовсе, даже когда координаты маленькие. Цена - лишний байт памяти, польза - отсутствие целого класса ошибок.
Когда 64 бит действительно мало
| ситуация | почему |
|---|---|
| координаты до (например, после сложения) | уже произведение не помещается |
| сравнение расстояний как против при больших координатах | квадраты складываются, растёт вдвое |
| площадь считается без модуля и накапливается по многим фигурам | сумма не ограничена одной фигурой |
Лекарство - __int128: он есть в GCC, арифметика в нём медленнее раза в два-три, зато границы хватает до . Печатать его напрямую нельзя, но для предикатов печатать и не нужно - достаточно знака.
using i128 = __int128;
int sign(i128 v) { return v > 0 ? 1 : v < 0 ? -1 : 0; }
i128 area2 = (i128)(b.x - a.x) * (c.y - a.y) - (i128)(b.y - a.y) * (c.x - a.x);
Как оценивать быстро
Считайте показатели: координаты дают произведения , косые произведения - с небольшим множителем. Дальше сравнивайте с .
Если получилось «впритык», как здесь, - это повод не расслабляться, а проверить оценку на предельном тесте: квадрат во весь диапазон обычно и есть худший случай.