Как вычислить евклидово расстояние между двумя точками на плоскости (например, на экране) в C++?

Ответ

Расстояние вычисляется по формуле: distance = sqrt((x2 - x1)² + (y2 - y1)²).

Базовая реализация:

#include <cmath> // для std::sqrt, std::hypot
#include <iostream>

struct Point {
    double x;
    double y;
};

double distance_simple(const Point& a, const Point& b) {
    double dx = b.x - a.x;
    double dy = b.y - a.y;
    return std::sqrt(dx * dx + dy * dy);
}

int main() {
    Point p1{1.0, 2.0};
    Point p2{4.0, 6.0};
    std::cout << "Distance: " << distance_simple(p1, p2) << std::endl; // 5.0
    return 0;
}

Практические улучшения и замечания:

  1. Используйте std::hypot (C++11): Эта функция специально предназначена для вычисления гипотенузы, она предотвращает переполнение и потерю точности.
    double distance_better(const Point& a, const Point& b) {
        return std::hypot(b.x - a.x, b.y - a.y);
    }
  2. Избегайте извлечения квадратного корня, если это возможно: Во многих алгоритмах (например, для сравнения расстояний) достаточно квадрата расстояния, что экономит ресурсы.
    double squared_distance(const Point& a, const Point& b) {
        double dx = b.x - a.x;
        double dy = b.y - a.y;
        return dx * dx + dy * dy;
    }
    // Сравнение: if (squared_distance(p1, p2) < radius*radius) ...
  3. Шаблонная реализация для разных типов данных:
    template<typename T>
    auto distance(const T& x1, const T& y1, const T& x2, const T& y2) -> decltype(std::hypot(x1, y1)) {
        return std::hypot(x2 - x1, y2 - y1);
    }
    // Работает с float, double, long double.
  4. Для целочисленных координат: Используйте double или long double для результата, чтобы избежать потери точности, но будьте осторожны с переполнением при вычислении квадратов больших чисел (используйте long long для промежуточных вычислений).

Ответ 18+ 🔞

А, ну вот, классика жанра, ебать мои старые костыли! Всегда одно и то же: «расстояние между двумя точками». Как будто мы на геометрии в седьмом классе, ёпта.

Смотри, вот тебе формула, святая святых: distance = sqrt((x2 - x1)² + (y2 - y1)²). Ну, типа, теорема Пифагора, которую все забыли сразу после школы. Хуй с горы, сейчас напомним.

Вот, смотри, самый простой код, чтоб мозги не взорвать сразу:

#include <cmath> // для std::sqrt, std::hypot
#include <iostream>

struct Point {
    double x;
    double y;
};

double distance_simple(const Point& a, const Point& b) {
    double dx = b.x - a.x;
    double dy = b.y - a.y;
    return std::sqrt(dx * dx + dy * dy);
}

int main() {
    Point p1{1.0, 2.0};
    Point p2{4.0, 6.0};
    std::cout << "Distance: " << distance_simple(p1, p2) << std::endl; // 5.0
    return 0;
}

Всё, вроде работает. Но это же пиздопроебибна какая-то, наивная реализация! Как будто на дворе 2002-й год. Сейчас есть нюансы, о которых твой препод, скорее всего, и не заикался.

Во-первых, забудь про std::sqrt в лоб, как страшный сон. С C++11 есть std::hypot. Эта хитрая жопа умная, она не переполнится и точность не потеряет, даже если числа овердохуища большие. Выглядит проще, да и правильнее.

double distance_better(const Point& a, const Point& b) {
    return std::hypot(b.x - a.x, b.y - a.y);
}

Во-вторых, часто корень — это лишняя работа. Представь, тебе нужно просто сравнить, какое расстояние меньше. Зачем тебе этот тяжёлый sqrt, если можно сравнить квадраты расстояний? Экономия — мать движняка, чувак.

double squared_distance(const Point& a, const Point& b) {
    double dx = b.x - a.x;
    double dy = b.y - a.y;
    return dx * dx + dy * dy;
}
// Использовать вот так: if (squared_distance(p1, p2) < radius*radius) ...

В-третьих, сделай это универсальным. А то вдруг тебе понадобится не double, а float? Или, ядрёна вошь, long double? Завязывай с копипастой, пиши шаблон.

template<typename T>
auto distance(const T& x1, const T& y1, const T& x2, const T& y2) -> decltype(std::hypot(x1, y1)) {
    return std::hypot(x2 - x1, y2 - y1);
}
// Работает с float, double, long double.

И последнее, про целые числа. Если у тебя координаты — int, будь готов к пиздецу. При вычитании и возведении в квадрат можно так запросто вылететь за пределы int. Используй long long для промежуточных расчётов, а результат всё равно в double засунь, а то корень из целого — это моветон, доверия ебать ноль.

В общем, суть в чём: не пиши как в учебнике. Думай, для чего тебе расстояние. Сравниваешь — бери квадрат. Боишься переполнения — hypot. Нужна универсальность — шаблон. А иначе получится мартышлюшка с кодом, который только на игрушечных примерах работает.