1

オブジェクトを保存したいのですがstd::setPoint3D比較関数は次のように定義されています (辞書順):

bool operator<(const Point3D &Pt1, const Point3D &Pt2)
{
    const double tol = 1e-5;

    if(fabs(Pt1.x() - Pt2.x()) > tol)
    {
        return Pt1.x() < Pt2.x();
    }    
    else if(fabs(Pt1.y() - Pt2.y()) > tol)
    {
        return Pt1.y() < Pt2.y();
    }
    else if(fabs(Pt1.z() - Pt2.z()) > tol)
    {
        return Pt1.z() < Pt2.z();
    }
    else
    {
        return false;
    }
}

場合によってsetは、同じ点が含まれている場合があります。問題は比較機能にあると思いますが、正確には問題が見つかりません。どんな助けでも大歓迎です!

4

1 に答える 1

7

許容範囲の概念は、推移的ではないため、厳密な弱い順序付けを正しく確立しません。例として、公差が であると想像してください1。今考えてみましょう:

a = 1
b = 2
c = 3

ここに:!(a<b)!(b<c), しかしa<c. これは、厳密な弱い順序付けの推移性の要件に明らかに違反しています。

許容範囲を持ちながら厳密な弱い順序付けでもある比較を実装したい場合は、すべての値を一貫した方法 (例: 、、1.5 => 2など) で丸め、丸めた値を比較する必要があります。0.75 => 12.3 => 2

s がすでにこれを行っているため、これを行うことは非常に無意味に思えdoubleますが、可能な限り最大の精度で行います。あなたがそれを見つけたとき、あなたはまだ奇妙な振る舞いをするでしょう1.4999999... != 1.5.

次のようにコンパレータを記述し、許容範囲の概念を放棄する必要があります。

bool operator<(const Point3D &Pt1, const Point3D &Pt2)
{
    //This can be replaced with a member/free function if it is used elsewhere
    auto as_tie = [](Point3D const &Pt) {
        //assumes the member functions return references
        //to the internal `Point3D` values.
        return std::tie(Pt.x(), Pt.y(), Pt.z());
    };
    return as_tie(Pt1) < as_tie(Pt2);
}

絶対に公差が必要な場合は、値を に入れるとすぐPoint3Dに丸めるか、比較の直前に値を丸めます (システムの他の要件によって異なります)。

于 2014-06-09T11:05:42.110 に答える