假設曲線上有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