QCOMPARE doesn't like QPointF



  • Hi,

    I've seen examples of source code using QCOMPARE to test QPointFs - http://koffice2.sourcearchive.com/documentation/2.0.1/TestPosition_8cpp-source.html

    In my case it doesnt work.

    Here's the source
    @
    // This passes
    QCOMPARE(_mockEntity->getPosition(), QPointF(0,0));

    _action->update(1000);
    // This fails
    QCOMPARE(_mockEntity->getPosition(), QPointF(6,8));
    @

    and heres the result:
    @FAIL! : ActionMoveTest::tst_update() Compared values are not the same
    Actual (_mockEntity->getPosition()): QPointF(6,8)
    Expected (QPointF(6,8)): QPointF(6,8)
    @

    QPointF(6,8) != QPointF(6,8)? I thought the floating point comparison issue was handled by some clever internal FuzzyCompare?

    Debug shows the getPosition call returns (6.0000000894069672, 8.0000001192092896).

    Am I doing something wrong?

    Thanks



  • You are using floating point which have precision issues, for the sake of comparing such numbers there is qFuzzyCompare() which has a certain tolerance. You can write your own function to compare QRectF using qFuzzyCompare().

    From the "documentation":http://doc.qt.digia.com/qt/qtest.html#QCOMPARE:

    bq. The QCOMPARE macro compares an actual value to an expected value using the equals operator.

    which is no good for floating point numbers...

    bq. In the case of comparing floats and doubles, qFuzzyCompare() is used for comparing. This means that comparing to 0 will likely fail. One solution to this is to compare to 1, and add 1 to the produced output.

    So you need something like:

    @bool compareQRectF(const QRectF &a, const QRectF &b){
    return qFuzzyCompare(a.x(), b.x()) && qFuzzyCompare(a.y(), b.y());
    }@



  • Well, the docs also say:
    [quote]QCOMPARE ( actual, expected )

    In the case of comparing floats and doubles, qFuzzyCompare() is used for comparing. This means that comparing to 0 will likely fail. One solution to this is to compare to 1, and add 1 to the produced output.[/quote]

    But I think the problem here is that you are NOT comparing floats or doubles here. You are comparing QPointF objects, so QCOMPARE will have to use the equals operator of the QPointF class. The qFuzzyCompare() function does not work on objects. It could, in theory, be used inside the implementation of QPointF::operator==, but apparently that is not the case. And there may be cases where you don't want that operator to be "fuzzy".



  • IMO QRectF should implement == with qFuzzyCompare(), it would make no sense to do it otherwise...

    EDIT:

    And indeed it does:

    @Q_DECL_CONSTEXPR inline bool operator==(const QRectF &r1, const QRectF &r2)
    {
    return qFuzzyCompare(r1.xp, r2.xp) && qFuzzyCompare(r1.yp, r2.yp)
    && qFuzzyCompare(r1.w, r2.w) && qFuzzyCompare(r1.h, r2.h);
    }@



  • Actually using QPointF, but no matter.

    Looking at my 4.8.2 source I see:
    @inline bool operator==(const QPointF &p1, const QPointF &p2)
    {
    return qFuzzyIsNull(p1.xp - p2.xp) && qFuzzyIsNull(p1.yp - p2.yp);
    }

    static inline bool qFuzzyIsNull(double d)
    {
    return qAbs(d) <= 0.000000000001;
    }
    @

    So my float error is 0.00000008940697 which is alot greater than the epsilon in QFuzzyIsNull.

    I guess I'll have to implement my own version with tolerance


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.