Reputation:
Let's say I have a function that calculates Euclidean distance between a pair of points. point
and point_pair
are two structs defined as:
struct point {
int x, y;
}
and
struct point_pair {
point a, b;
}
The following functions calculates the distance taking a pair of points as an input:
double calc_distance(point_pair pair)
{
return (sqrt((pair.a.x - pair.b.x) * (pair.a.x - pair.b.x) + (pair.a.y - pair.b.y) * (pair.a.y - pair.b.y)));
}
The function works fine for small point pair values; but for a point pair such as:
651760491 595516649
716636914 955747792
The output is -nan
I'm not sure how to workaround this, is there something else I should be using in place of double?
Here is the entire code: https://pastebin.com/5XEr9bTD
Upvotes: 1
Views: 161
Reputation: 11940
The best would be to not use int
for point coordinates at all:
#include <iostream>
#include <cmath>
struct point { double x, y; };
struct point_pair { point a, b; };
double calc_distance(point_pair pair) {
return (std::sqrt((pair.a.x - pair.b.x) * (pair.a.x - pair.b.x) + (pair.a.y - pair.b.y) * (pair.a.y - pair.b.y)));
}
int main() {
point_pair pp{{651760491, 595516649}
, {716636914, 955747792}};
std::cout << calc_distance(pp) << '\n';
}
But if you have a reason to do that, well, then at least convert coordinate differences to double
:
struct point { int x, y; };
struct point_pair { point a, b; };
double calc_distance(point_pair pair) {
return (std::sqrt(double(pair.a.x - pair.b.x) * (pair.a.x - pair.b.x) + double(pair.a.y - pair.b.y) * (pair.a.y - pair.b.y)));
}
Because otherwise you face integer overflow at large orders, and signed overflow is an UB in C++.
Upvotes: 2
Reputation: 20080
Right way to do it would be use of standard hypot()
function.
https://en.cppreference.com/w/cpp/numeric/math/hypot
"Computes the square root of the sum of the squares of x and y, without undue overflow or underflow at intermediate stages of the computation."
Upvotes: 5