假设我有一个计算一对点之间的欧几里得距离的函数。 point
和point_pair
是定义为的两个结构:
struct point {
int x, y;
}
和
struct point_pair {
point a, b;
}
以下功能以一对点作为输入来计算距离:
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)));
}
该功能适用于较小的点对值;但是对于点对,例如:
651760491 595516649
716636914 955747792
输出为-nan
我不确定如何解决此问题,我还应该使用其他方法代替double吗?
这是完整的代码:https://pastebin.com/5XEr9bTD
答案 0 :(得分:5)
正确的方法是使用标准hypot()
函数。
https://en.cppreference.com/w/cpp/numeric/math/hypot
“计算x和y的平方和的平方根,在计算的中间阶段不会出现不适当的上溢或下溢。”
答案 1 :(得分:2)
最好不要使用int
作为点坐标:
#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';
}
但是,如果您有这样做的理由,那么至少将坐标差转换为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)));
}
因为否则,您将面临大订单的整数溢出,而有符号溢出是C ++中的UB。