Unit test could usefully output more significant digits to log files?

In setting up a test for math function accuracy, I incorrectly coded thus: BOOST_CHECK_EQUAL(sin(0.5), 0.479426); and got the somewhat puzzling - apparently wrong - message error in "call_test_main": test sin(0.5) == 0.479426 failed [0.479426 != 0.479426] On most days of the week, one would expect [0.479426 == 0.479426]! I should of course have written BOOST_CHECK_EQUAL(sin(0.5), 0.47942553860420301); (or used BOOST_CHECK_CLOSE(sin(0.5), 0.47942553860420301, 1e-16);) But I wonder if the test program would be even more helpful if it output all possibly significant digits. In test_tools.hpp, I have added an increase to the ostream precision (default only 6 digits) int print_log_value thus template<typename T> struct print_log_value { void operator()( std::ostream& ostr, T const& t ) { if(std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2) { // Show all possibly significant digits (for example, 17 for 64-bit double). ostr.precision(2 + std::numeric_limits<T>::digits * 301/1000); } ostr << t; // by default print the value. } }; so that the message is no longer test sin(0.5) == 0.479426 failed [0.47942553860420301 != 0.47942600000000002] and my folly obvious. And after the original mistake is corrected BOOST_CHECK_EQUAL(sin(0.5), 0.47942553860420301); The log file reports: info: sin(0.5) == 0.47942553860420301 passed. Paul PS (It does not appear to possible to change the precision 'externally' by calling cout.precision(17); myTestLog.precision(17); probably because ostr in test is contructed with default precision). Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539 561830 +44 7714 330204 mailto: pbristow@hetp.u-net.com

At Monday 2004-07-26 10:33, you wrote:
In setting up a test for math function accuracy, I incorrectly coded thus:
BOOST_CHECK_EQUAL(sin(0.5), 0.479426);
and got the somewhat puzzling - apparently wrong - message
error in "call_test_main": test sin(0.5) == 0.479426 failed [0.479426 != 0.479426]
On most days of the week, one would expect [0.479426 == 0.479426]!
I should of course have written
BOOST_CHECK_EQUAL(sin(0.5), 0.47942553860420301);
(or used
BOOST_CHECK_CLOSE(sin(0.5), 0.47942553860420301, 1e-16);)
But I wonder if the test program would be even more helpful if it output all possibly significant digits.
In test_tools.hpp, I have added an increase to the ostream precision (default only 6 digits) int print_log_value thus
template<typename T> struct print_log_value { void operator()( std::ostream& ostr, T const& t ) { if(std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2) { // Show all possibly significant digits (for example, 17 for 64-bit double). ostr.precision(2 + std::numeric_limits<T>::digits * 301/1000);
is there some reason you didn't: ostr.precision(2 + std::numeric_limits<T>::digits10); instead of estimating log(2)? (301/1000)
} ostr << t; // by default print the value. } };
so that the message is no longer
test sin(0.5) == 0.479426 failed [0.47942553860420301 != 0.47942600000000002]
and my folly obvious.
And after the original mistake is corrected
BOOST_CHECK_EQUAL(sin(0.5), 0.47942553860420301);
The log file reports:
info: sin(0.5) == 0.47942553860420301 passed.
Paul
PS (It does not appear to possible to change the precision 'externally' by calling
cout.precision(17);
myTestLog.precision(17);
probably because ostr in test is contructed with default precision).
Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539 561830 +44 7714 330204 mailto: pbristow@hetp.u-net.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

| -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of Victor A. | Wagner Jr. | Sent: 26 July 2004 19:53 | To: boost@lists.boost.org | Subject: Re: [boost] Unit test could usefully output more | significantdigits to log files? | | >In test_tools.hpp, I have added an increase to the ostream precision | >(default only 6 digits) int print_log_value thus | > | > template<typename T> | > struct print_log_value { | > void operator()( std::ostream& ostr, T const& t ) | > { | > if(std::numeric_limits<T>::is_specialized && | >std::numeric_limits<T>::radix == 2) | > { // Show all possibly significant digits (for example, | 17 for 64-bit | >double). | > ostr.precision(2 + std::numeric_limits<T>::digits * 301/1000); | | is there some reason you didn't: | ostr.precision(2 + std::numeric_limits<T>::digits10); | instead of estimating log(2)? (301/1000) | Yes - it was to get all possibly significant digits, rather than all guaranteed. You need to estimate log2 because the compiler won't do the necessary fp calculations. Sometimes this is more helpful - and since this a diagnostic, it seemed a little better. However digits10 would also be much better than default 6 precision. Paul Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539 561830 +44 7714 330204 mailto: pbristow@hetp.u-net.com

template<typename T> struct print_log_value { void operator()( std::ostream& ostr, T const& t ) { if(std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2) { // Show all possibly significant digits (for example, 17 for 64-bit double). ostr.precision(2 + std::numeric_limits<T>::digits * 301/1000); } ostr << t; // by default print the value. } };
Actually it's in my TODO list. I consider using this solution after release. Gennadiy.

Good. The code below works for me - and I will advise any problems I encounter. http://http.cs.berkley.edu/~wkahan/ieee754status/ieee754.ps is about the number of decimal places. The formula below generates the values W Kahan, of IEEE754 fame, gives (for example 17 for 64-bit double). To amplify my reply to Vicotr Wagner, the following example showing the effect of a few least significant bit changes and that you need precision 17 to show this reliably. double d = 1.; for (int i = 1; i < 10; i++) { d = _nextafter(d, +999.); // increment least siginificant bit. cout << i << ' ' << setw(20) << setprecision(15) << d << ' '<< setw(20) << setprecision(16) << setw(20)<< d << ' ' << setprecision(17) << d << endl; } Outputs bits changed precision 15 precision 16 precision 17 1 1 1 1.0000000000000002 2 1 1 1.0000000000000004 3 1 1.000000000000001 1.0000000000000007 4 1 1.000000000000001 1.0000000000000009 5 1 1.000000000000001 1.0000000000000011 6 1 1.000000000000001 1.0000000000000013 7 1 1.000000000000002 1.0000000000000016 8 1 1.000000000000002 1.0000000000000018 9 1 1.000000000000002 1.000000000000002 However, I note that this involves lots of calls to ostr.precision() and perhaps it can be don't more efficiently by a single call when ostream just after constructed. But it works and the cost is small. Paul | -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of Gennadiy Rozental | Sent: 27 July 2004 07:12 | To: boost@lists.boost.org | Subject: [boost] Re: Unit test could usefully output more | significant digitstolog files? | | > template<typename T> | > struct print_log_value { | > void operator()( std::ostream& ostr, T const& t ) | > { | > if(std::numeric_limits<T>::is_specialized && | > std::numeric_limits<T>::radix == 2) | > { // Show all possibly significant digits (for example, | 17 for 64-bit | > double). | > ostr.precision(2 + std::numeric_limits<T>::digits * 301/1000); | > } | > ostr << t; // by default print the value. | > } | > }; | | | Actually it's in my TODO list. | | I consider using this solution after release. | | Gennadiy. | | | | _______________________________________________ | Unsubscribe & other changes: | http://lists.boost.org/mailman/listinfo.cgi/boost | |
participants (3)
-
Gennadiy Rozental
-
Paul A Bristow
-
Victor A. Wagner Jr.