
| -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of John Maddock | Sent: 12 November 2005 17:16 | To: boost@lists.boost.org | Subject: Re: [boost] [Test] BOOST_CHECK_CLOSE Feature request | | > comparing IEEE floats at | http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm | > | > This makes use of the property that IEEE floating point formats are | > lexicographically ordered when reinterpreted as an appropriate length | > signed integer. It appears you can use this to define a closeness | > measure based on how many units in the last place the two numbers | > differ by (equivalently, if you enumerated all possible floats and | > counted how far | > away one number is from the other in the enumeration). I only just | > came across it now so I havn't tried playing with it yet, but it | > looks like it would make a useful closeness measure. I HAVE been playing with it, briefly, and seems to work as expected for MS 8.0 using int for float (or should that be __int32?) using __int64 type for double (and of course long double since it is the same). double a = 1.2; double b = 1.199999999999999; __int64 aInt64 = *(__int64*)&a; // float as 64-bit integer. __int64 bInt64 = *(__int64*)&b; cout << "a = " << a << " " << hex << aInt64 << endl; cout << "b = " << b << " " << hex << bInt64 << endl; __int64 d = aInt64 - bInt64; cout << "diff = " << hex << d << endl; a = 1.2 3ff3333333333333 b = 1.2 3ff333333333332f diff = 4 bool AlmostEqual2sComplement(double A, double B, int maxUlps); cout << boolalpha << AlmostEqual2sComplement(a, b, 2) << endl; outputs false, as expected because difference is 4. But of course, this is the simple case of 64-bit double. No doubt other exotic types can also be compared similarly with some bit twiddling, assuming we can select the right int to match the floating-point type. If int is 64-bit and float is only 32 should still work? But for now perhaps we can test and if not implemented then just give up: // Check is IEEE 754 - but really want a macro. if (!numeric_limits<double>::is_iec559) { // Code below is unsuitable. cout << "is NOT IEC559!" << endl; return -1; } and of course, this doesn't work C1017: invalid integer constant expression #if (!numeric_limits<double>::is_iec559) # pragma error ("NOT IEC559!") #endif #if ((DBL_MANT_DIG == 53) && (DBL_RADIX == 2) && (DBL_MAX_EXP == 1024)) # pragma message ("Is very probably IEC559.") // Want to give up here with pragma error, or something? #endif But I don't know if any of this takes account of (wrong-)endianness. For example, VAX layout is different? Boost test doesn't seem to rely on floating-point layout? Any experts on this, either on an IS_IEEE macro, or endianness? Paul -- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB Phone and SMS text +44 1539 561830, Mobile and SMS text +44 7714 330204 mailto: pbristow@hetp.u-net.com www.hetp.u-net.com