QCOMPARE有两个浮点无穷大值

时间:2017-09-29 14:57:40

标签: c++ qt floating-point infinity qtestlib

QCOMPARE(
    std::numeric_limits<double>::infinity(),
    std::numeric_limits<double>::infinity());

失败了:

Compared doubles are not the same (fuzzy compare)
       Actual   (std::numeric_limits<double>::infinity()): inf
       Expected (std::numeric_limits<double>::infinity()): inf
       Loc: [...]

问题

为什么这会失败?有没有一个好的解决方法(而不是使用QVERIFY)?

更新

我的意思是从测试作者的角度来解决问题。期望提供具有非无限的实际值的适当诊断。而不是

QCOMPARE(val, std::numeric_limits<double>::infinity());

一个人可以

QVERIFY(val == std::numeric_limits<double>::infinity()))

但如果检查失败,则生成的诊断消息中不会显示val的值。看起来像开发人员的主要疏忽。 那么我是否必须推出自己的宏,并进行与QCOMPARE类似的精确比较?这里有什么建议?

此外,很明显qFuzzyCompare不支持某些角落案例。但我希望能更深入地解释为什么会出现这种情况。

3 个答案:

答案 0 :(得分:2)

QCOMPARE在比较浮点数和双精度数的情况下,使用qFuzzyCompare()。 (http://doc.qt.io/qt-5/qtest.html#QCOMPARE

基于(http://doc.qt.io/qt-5/qtglobal.html#qFuzzyCompare),Qt文档,它自己说比较无穷大是行不通的。 - “请注意,比较p1或p2为0.0的值不起作用,也不比较其中一个值为NaN或无穷大的值

我的猜测,为什么无穷无法比较,无穷大没有特定值,我的意思是“ infinity-1 ”也是无穷大。那么显然比较是一个问题。

<强> 解决方法:

如果你想比较无穷大,那么使用下面的函数并比较返回的布尔值。

bool qIsInf(double d)

http://doc.qt.io/qt-5/qtglobal.html#qIsInf

答案 1 :(得分:1)

由于仍然没有工作示例,我在这里发布了我自己的宏:

#include <qtestcase.h>

#define COMPARE_DBL(actual, expected, epsilon) \
do {\
    if (!QTest::compare_helper((qAbs(actual - expected) <= epsilon), \
                               QString{"Compared values are not the same in respect to epsilon %1"} \
                                    .arg(epsilon).toLocal8Bit().constData(), \
                               QTest::toString(actual), \
                               QTest::toString(expected), \
                               #actual, #expected, __FILE__, __LINE__)) \
        return;\
} while (false)

它打印出 Qt 格式化的错误消息并正确中断测试用例。

答案 2 :(得分:0)

我最终写了一个自定义的marco。它模仿QCOMPARE输出并且不会突出。

这是(随意重复使用):

inline void isEqualsExactly(
    const double actual,
    const double expected,
    const std::string& actualName,
    const std::string& expectedName)
{
    if(expected == actual)
        return;
    std::stringstream warn;
    const size_t w = std::max(actualName.length(), expectedName.length());
    warn << "Compared values are not the same" << std::endl;
    warn << "   Actual   " << std::setw(w) << std::setfill(' ') << actualName;
    warn << ": " << std::to_string(actual) << std::endl;
    warn << "   Expected " << std::setw(w) << std::setfill(' ') << expectedName;
    warn << ": " << std::to_string(expected);
    QFAIL(warn.str().c_str());
}

#define QCOMPARE_EXACT(actual, expected) \
    isEqualsExactly(actual, expected, #actual, #expected);

用法:

const double val = 0;
const double infinity = std::numeric_limits<double>::infinity();
QCOMPARE_EXACT(val, infinity);

输出:

FAIL!  : TestName Compared values are not the same
   Actual        val: 0.000000
   Expected infinity: inf  
   Loc: [link to location in file]

P.S。我同意,这应该是一个功能请求。情况很荒谬。如果我要制作一个,我会更新帖子。