/*! Returns the number of representable floating-point numbers between \a a and \a b. This function serves the same purpose as \c{qFloatDistance(float, float)}, but returns the distance between two \c double numbers. Since the range is larger than for two \c float numbers (\c{[-DBL_MAX,DBL_MAX]}), the return type is quint64. \sa qFuzzyCompare() \since 5.2 \relates <QtGlobal> */ Q_CORE_EXPORT quint64 qFloatDistance(double a, double b) { static const quint64 smallestPositiveFloatAsBits = 0x1; // denormalized, (SMALLEST) /* Assumes: * IEE754 format double precision * Integers and floats have the same endian */ Q_STATIC_ASSERT(sizeof(quint64) == sizeof(double)); Q_ASSERT(qIsFinite(a) && qIsFinite(b)); if (a == b) return 0; if ((a < 0) != (b < 0)) { // if they have different signs if (a < 0) a = -a; else /*if (b < 0)*/ b = -b; return qFloatDistance(0.0, a) + qFloatDistance(0.0, b); } if (a < 0) { a = -a; b = -b; } // at this point a and b should not be negative // 0 is special if (!a) return d2i(b) - smallestPositiveFloatAsBits + 1; if (!b) return d2i(a) - smallestPositiveFloatAsBits + 1; // finally do the common integer subtraction return a > b ? d2i(a) - d2i(b) : d2i(b) - d2i(a); }
/*! Returns the number of representable floating-point numbers between \a a and \a b. This function provides an alternative way of doing approximated comparisons of floating-point numbers similar to qFuzzyCompare(). However, it returns the distance between two numbers, which gives the caller a possibility to choose the accepted error. Errors are relative, so for instance the distance between 1.0E-5 and 1.00001E-5 will give 110, while the distance between 1.0E36 and 1.00001E36 will give 127. This function is useful if a floating point comparison requires a certain precision. Therefore, if \a a and \a b are equal it will return 0. The maximum value it will return for 32-bit floating point numbers is 4,278,190,078. This is the distance between \c{-FLT_MAX} and \c{+FLT_MAX}. The function does not give meaningful results if any of the arguments are \c Infinite or \c NaN. You can check for this by calling qIsFinite(). The return value can be considered as the "error", so if you for instance want to compare two 32-bit floating point numbers and all you need is an approximated 24-bit precision, you can use this function like this: \code if (qFloatDistance(a, b) < (1 << 7)) { // The last 7 bits are not // significant // precise enough } \endcode \sa qFuzzyCompare() \since 5.2 \relates <QtGlobal> */ Q_CORE_EXPORT quint32 qFloatDistance(float a, float b) { static const quint32 smallestPositiveFloatAsBits = 0x00000001; // denormalized, (SMALLEST), (1.4E-45) /* Assumes: * IEE754 format. * Integers and floats have the same endian */ Q_STATIC_ASSERT(sizeof(quint32) == sizeof(float)); Q_ASSERT(qIsFinite(a) && qIsFinite(b)); if (a == b) return 0; if ((a < 0) != (b < 0)) { // if they have different signs if (a < 0) a = -a; else /*if (b < 0)*/ b = -b; return qFloatDistance(0.0F, a) + qFloatDistance(0.0F, b); } if (a < 0) { a = -a; b = -b; } // at this point a and b should not be negative // 0 is special if (!a) return f2i(b) - smallestPositiveFloatAsBits + 1; if (!b) return f2i(a) - smallestPositiveFloatAsBits + 1; // finally do the common integer subtraction return a > b ? f2i(a) - f2i(b) : f2i(b) - f2i(a); }
void tst_QNumeric::floatDistance_double() { QFETCH(double, val1); QFETCH(double, val2); QFETCH(quint64, expectedDistance); #ifdef Q_OS_QNX QEXPECT_FAIL("denormal", "See QTBUG-37094", Continue); #endif QCOMPARE(qFloatDistance(val1, val2), expectedDistance); }