假设曲线上有100000个点y = x^2
。你想找到这些点的凸包。所有的坐标都是浮点数。当浮动精度问题出现时,您如何能够实际解决凸包问题?
在我的格雷厄姆扫描实现中,我操作浮点数的唯一地方是当我最初按坐标对所有点进行排序,然后我有一个函数确定三点是左转还是右转。
点:
struct point {
double x;
double y;
};
排序比较:
inline bool operator() (const point &p1, const point &p2) {
return (p1.x < p2.x) || (p1.x == p2.x && p1.y > p2.y);
}
左/右转:
inline int ccw(point *p1, point *p2, point *p3) {
double left = (p1->x - p3->x)*(p2->y - p3->y);
double right = (p1->y - p3->y)*(p2->x - p3->x);
double res = left - right;
return res > 0;
}
我的计划说出来的100万点仅68894的部分凸包。但是因为它们在曲线上,它们都应该是凸包的一部分。
对你的眼睛不会有任何区别。见下图。红点是凸包的一部分。
image http://oi57.tinypic.com/t8lsvs.jpg
但如果你看看足够接近,并放大到分,你会看到,他们中的一些是蓝色的,所以它们并不包括在该凸包。现在
image http://oi61.tinypic.com/2eol37a.jpg
我最初的假设是,浮点错误导致此问题。
我想我可以使用具有浮点数任意精度的外部库,但我更感兴趣的是,我们有例如C++中的简单数据类型。
我该如何提高准确度?我读过关于epsilon的内容,但是如何在这里使用epsilon帮助?我仍然会假设一些接近彼此的点是相同的,所以我不会得到接近100%的准确度。
解决此问题的最佳方法是什么?
你试过'长双'吗? – mch 2014-09-30 14:16:12
您的凸包算法可能是正确的,但是当您最初评估y = x^2时会发生舍入? – ajclinto 2014-09-30 14:17:14
首先,没有有限的精度会让你表示实数。其次,你绘制的点是近似值。第三,真正的建设性实在(无限精确)无法与你想比较的方式进行比较。第五,你为什么在意? (你有什么目的,因此重要的船体) – Yakk 2014-09-30 14:19:05